产品要让点加购物车的小球从按钮飞到顶部图标,直线飞过去像被吸走,要的是先冲出去再落下来的弧线。第一反应是写个贝塞尔曲线,调了半天都对不上。拆成横竖两个方向各自跑,弧线自然就出来了。

横向匀速,纵向加速

外层元素管横轴,用 linear 匀速平移;内层元素管纵轴,用 ease-in 模拟重力加速。两个动画同时跑,合成轨迹就是抛物线。关键是分两层,同一个元素上写两个方向的 transform 动画,后面的会把前面的覆盖掉。结构上多包一个 div,成本很低。

.fly { animation: x .6s linear forwards; } .ball { animation: y .6s ease-in forwards; } @keyframes x { to { transform: translateX(240px); } } @keyframes y { to { transform: translateY(-180px); } }

落点要对准图标,横向距离和纵向高度按实际位置算出来,别写死像素。容器宽度一变,写死的值就飞偏了,用变量或者运行时量一次都行。

想更省事就用 offset-path

现代浏览器支持 offset-path 直接给一条路径,元素沿着走,弧度和转弯都好控制。缺点是老版本浏览器表现不稳,做活动页要兼容旧机型时得准备降级方案,检测到不支持就走直线。

  • 动画结束记得把元素移除,不然点十次留十个节点。
  • 用 transform 而不是改 left 和 top,前者走合成层,不触发重排。
  • 给动画加减少动态效果的判断,系统开了对应选项就别飞。
  • 连续点击时先清掉上一次的动画,避免几个球叠在一起。

选型建议:只需要一条固定弧线,两层动画足够,代码短也好维护;路径复杂或者要绕着元素走,再上 offset-path。先量清楚起点和终点,再决定用哪种。