使用Javascript的Element.animate()时动画事件无法触发如何解决?
问题产生原因
你混淆了两类不同动画体系的事件监听规则:
- 代码中监听的
animationstart、animationend是CSS动画/过渡专属的DOM事件,只有用@keyframes定义、通过CSS类切换触发的动画,才会在绑定的DOM元素上触发这两个事件。 - 你调用的
Element.animate()属于Web Animations API(WAAPI),调用后会返回一个独立的Animation实例对象,它的生命周期事件不会冒泡到DOM元素上,也不会触发CSS动画相关的DOM事件,因此你绑定在DOM元素上的监听回调永远不会被触发。
修复方案
方案1:使用Web Animations API原生事件监听(推荐,无需改动原有动画逻辑)
直接给animate()返回的Animation实例绑定对应事件即可,finish事件对应原需求的动画结束监听,如果需要监听动画开始,直接在调用animate方法后同步执行对应逻辑即可(WAAPI调用后默认立即执行动画,没有额外延迟的情况下和动画开始时机完全一致)。
修复后的代码示例:
window.onload = function () { let list = document.querySelector(".list"); let btn = document.querySelector(".btn"); btn.onclick = () => { console.log('start') // 等价原animationstart逻辑,动画触发即执行 const animation = list.animate([ // 关键帧 { transform: 'translateY(0px)' }, { transform: 'translateY(-24px)' } ], { // 时序配置 duration: 1000, fill: "forwards" }); // 绑定动画结束事件 animation.addEventListener('finish', () => { console.log('end'); }); } }
方案2:切换为CSS动画实现,保留原有事件监听
如果希望继续使用animationstart、animationend事件,可以把动画逻辑迁移到CSS中定义,通过切换类名触发动画:
- 先添加CSS定义:
/* 定义动画关键帧 */ @keyframes slideUp { from { transform: translateY(0px); } to { transform: translateY(-24px); } } /* 动画触发类 */ .list.slide-up { animation: slideUp 1s forwards; }
- 修改JS逻辑,点击时加类触发动画:
window.onload = function () { let list = document.querySelector(".list"); let btn = document.querySelector(".btn"); // 原事件监听可保留 list.addEventListener('animationstart', () => { console.log('start') }); list.addEventListener('animationend', () => { console.log('end'); }); btn.onclick = () => { // 先移除类再添加,避免第二次点击不触发动画 list.classList.remove('slide-up'); // 强制触发重排,让类移除生效后再添加 void list.offsetWidth; list.classList.add('slide-up'); } }
内容的提问来源于stack exchange,提问作者EMMANUEL EZEKA
相关产品推荐
相关产品推荐

