动画事件 + 用 JS 控制动画
CSS 动画会派发一组事件,JS 能监听;反过来 JS 也能通过 Web Animations API(element.getAnimations())拿到正在跑的动画并 pause / play / reverse。下面这个方块挂了全部事件监听,按钮分别 Add / Pause / Resume / Reverse / Remove,事件实时打到日志面板。
1 · 四个动画事件
| 事件 | 触发时机 |
|---|---|
animationstart |
event.animationName 给出 @keyframes 名称;event.elapsedTime 是动画已运行的时间(开始事件通常为 0,除非有负 delay)。 |
animationiteration |
每完成一轮(infinite / count > 1 时)触发一次。 |
animationend |
动画自然结束时触发(infinite 不会触发)。 |
animationcancel |
动画被中断时(如移除 class、display: none)触发。 |
JS/UI 与 CSS 动画不在同一线程,互不阻塞;主线程被脚本卡住时,合成线程上的动画照样推进。
Add 给方块加 .enable(开始无限 alternate 动画)触发 animationstart,每轮触发 animationiteration。Pause / Resume 改元素自身的 --play-state(CSS 变量)。Reverse 用 getAnimations() 拿到动画后
updatePlaybackRate(-playbackRate) 反转方向——注意 reverse() 在 infinite 动画上会因 effect end 为无穷大抛 InvalidStateError,它只适用于有限时长的动画。Remove 去掉 .enable 触发
animationcancel。事件同时也打到了浏览器 console。
2 · 用 JS 创建动画:element.animate()
前面都是 CSS 写好动画、JS 只去「拿到并控制」。Web Animations API 还能完全用 JS 创建动画——一行 element.animate(keyframes, options) 直接返回一个 Animation 对象,之后可调用 playbackRate(变速)、currentTime(跳转)、pause / play / reverse,还有 finished promise 等结束、commitStyles() 固化终态。
const anim = box.animate(
[{ transform: 'translateX(0)' }, { transform: 'translateX(240px)' }],
{ duration: 1500, iterations: Infinity, direction: 'alternate', easing: 'ease' }
);
anim.playbackRate = 3;
anim.currentTime = 750;
anim.pause(); anim.play();
anim.updatePlaybackRate(-anim.playbackRate);
anim.finished.then(() => {});
playbackRate = 3 变速(也可 anim.updatePlaybackRate(3));currentTime = 750 跳到某一时刻(单位 ms);updatePlaybackRate(-anim.playbackRate) 反向(infinite 动画不能用 reverse());finished.then(...) 在有限动画结束时 resolve。
animate() 返回的 Animation 把动画变成了可编程对象:变速、拖到任意时刻、监听结束都用 JS 完成,无需写 @keyframes / class。无限动画的 finished 不会 resolve;点「播放一次 → finished」用一个有限动画看它结束时的回调。
延伸阅读:Web Animations API · MDN——本页用到的 element.animate()、getAnimations()、Animation 对象(playbackRate / currentTime /
finished / commitStyles())的逐项参考与兼容表。