如何检测Web Animation API动画的创建?
如何检测Web Animation API动画的创建?
确实,目前Web Animation API并没有提供像transitionstart那样全局监听所有动画创建的原生事件,这一点确实有点遗憾😅。你提到的轮询document.getAnimations()是可行的,但确实不够优雅,下面给你几个更靠谱的思路:
1. 拦截核心动画创建API,统一监听
所有Web Animations(包括JS创建的Animation实例、CSS过渡/动画)最终都会依赖几个核心API,我们可以通过包装这些原生方法,在动画创建时触发自定义事件,实现全局监听:
拦截JS动画创建方法
比如重写Element.animate()和KeyframeEffect构造函数,在里面注入自定义逻辑:
// 保存原生Element.animate方法 const originalAnimate = Element.prototype.animate; Element.prototype.animate = function(keyframes, options) { const animation = originalAnimate.call(this, keyframes, options); // 触发自定义全局事件,携带新创建的动画实例 document.dispatchEvent(new CustomEvent('animationcreated', { detail: animation })); return animation; }; // 同样处理KeyframeEffect(如果有直接创建的情况) const originalKeyframeEffect = window.KeyframeEffect; window.KeyframeEffect = function(...args) { const effect = new originalKeyframeEffect(...args); return effect; };
统一CSS动画/过渡的监听
对于CSS触发的过渡和动画,我们可以把原生的transitionstart、animationstart事件也映射到自定义的全局事件里,这样就能统一处理所有类型的动画:
// 监听CSS过渡开始 document.addEventListener('transitionstart', (e) => { document.dispatchEvent(new CustomEvent('animationcreated', { detail: e.target.getAnimations()[0] })); }); // 监听CSS动画开始 document.addEventListener('animationstart', (e) => { document.dispatchEvent(new CustomEvent('animationcreated', { detail: e.target.getAnimations()[0] })); });
之后你只需要监听自定义的animationcreated事件,就能捕获所有类型的动画创建了:
document.addEventListener('animationcreated', (e) => { const newAnimation = e.detail; console.log('新动画创建:', newAnimation); // 这里可以做你需要的处理,比如记录、绑定后续逻辑等 });
2. 优化轮询方案(退而求其次的选择)
如果你不想修改原生API,轮询是备选方案,但可以优化得更精准:用requestAnimationFrame代替固定间隔的setTimeout,因为动画的创建必然发生在渲染帧周期内,这样能保证不会错过,同时性能也更好:
// 用Set存储已发现的动画,避免重复处理 const knownAnimations = new Set(); function checkForNewAnimations() { const currentAnimations = document.getAnimations(); currentAnimations.forEach(anim => { if (!knownAnimations.has(anim)) { knownAnimations.add(anim); console.log('检测到新动画:', anim); // 处理新动画的逻辑 } }); // 下一帧继续检查 requestAnimationFrame(checkForNewAnimations); } // 启动轮询 checkForNewAnimations();
结合你的代码示例测试
比如在你提供的代码里,当animatedElt触发过渡时,上面的两种方法都能捕获到这个动画的创建。如果之后你用JS调用animatedElt.animate()创建新动画,也能被统一监听。
备注:内容来源于stack exchange,提问作者tobiasBora
相关产品推荐
相关产品推荐

