必须用两个dom元素协作,父容器控制水平匀速运动,子元素控制垂直先升后降运动,通过嵌套合成抛物线轨迹;单元素因transform属性冲突无法独立调控xy节奏。

抛物线动画必须用两个 DOM 元素协作
单个元素无法同时独立控制 X 和 Y 方向的运动节奏——transform: translateX() 和 translateY() 在同一动画中会相互干扰,导致轨迹塌缩为斜线或抖动。真正可用的方案是父容器负责水平位移(匀速),子元素负责垂直位移(先升后降),靠嵌套关系合成抛物线。
常见错误是只 clone 一个 <img> 就开始 animating,结果 y 轴根本飞不起来,或者最高点偏移严重。正确做法是:
- 用
document.createElement('div')创建外层容器(.flyer-outer),设position: fixed、初始left/top为起点 - 再创建内层元素(
.flyer-inner),append 进去,只负责transform: translateY() - 两者分别绑定不同缓动:外层用
cubic-bezier(0.2, 0.8, 0.4, 1)(模拟水平推进感),内层用cubic-bezier(0.39, -0.4, 0.5, 0)(制造上扬再下坠)
getBoundingClientRect() 必须在渲染后调用
如果在点击事件回调里立刻调 btn.getBoundingClientRect(),可能拿到的是旧坐标——尤其当商品列表是懒加载、或购物车图标由 Vue/React 动态插入时。DOM 还没重排完成,坐标就错了,抛物线直接飞偏。
稳妥做法只有两种:
- 包一层
requestAnimationFrame(() => { /* 获取坐标 + 启动动画 */ }),确保在下一帧执行 - 或用
setTimeout(() => {}, 0)(兼容性更好,但不如 RAF 精确) - 千万别依赖
offset()(jQuery)或getComputedStyle(),它们不反映实时布局位置
element.animate() 在 Safari 16.4+ 才可靠
想用 Web Animations API 写真抛物线?得先看浏览器支持。Safari 直到 16.4 版本才修复 element.animate() 对 transform 多属性插值的 bug,旧版本会出现 y 偏移突跳、缓动失效、甚至动画卡死。
生产环境建议按需降级:
- 检测
Element.prototype.animate是否存在且能正常返回Animation实例 - 若不支持,退回到
requestAnimationFrame手动更新style.transform - 别用 CSS
@keyframes+animation硬写路径——它无法动态计算最高点,每次起点终点变化都要重生成 keyframes
连点必须节流 + 动画节点及时销毁
用户狂点“加入购物车”,每个点击都新建一个 .flyer-outer,又不清理,3 秒内就能堆出 20+ 个 fixed 元素挂在 body 上。轻则内存暴涨,重则触发 iOS WebKit 的渲染限制,页面直接卡死。
关键控制点:
- 动画开始前检查
document.querySelectorAll('.flyer-outer').length > 3,超限则跳过本次动画 - 监听
animationend或webkitAnimationEnd,触发后立即el.remove() - 务必清除所有关联事件监听器(比如
onEnd回调里没调this.destory(),引用就一直挂着)
最易被忽略的是:动画中途用户切页或关闭 tab,这些 flyer 元素不会自动销毁——得在 beforeunload 或 visibilitychange 里兜底清理。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











