JS动画重复触发崩溃求助:复选框控制遮罩层显隐动画异常
解决遮罩层动画重复操作崩溃的问题
嘿,我一眼就发现问题所在了——你第二次勾选复选框时动画崩溃,核心原因是重复绑定了animationend事件,加上动画状态没有正确重置,导致后续的动画逻辑混乱。咱们一步步来修复:
问题诊断
- 事件监听叠加:每次取消勾选时,你都会给
overlay添加一个新的animationend监听器,但从未移除旧的。第二次取消操作后,监听器会叠加,动画结束时会多次执行隐藏逻辑,甚至和新的显示操作冲突。 - 动画状态残留:再次勾选显示遮罩时,之前的
disappear动画状态没有被完全重置,浏览器可能会沿用旧的动画属性,导致appear动画无法正常触发。
解决方案
我给你调整了代码,主要做了这几点优化:
- 使用一次性事件监听,避免监听器叠加
- 显示遮罩前重置动画状态,确保每次动画都是从头开始
- 缓存DOM元素,提升性能
修改后的完整代码
CSS(保持你的原有代码不变)
#overlay{ position:absolute; height: 100vh; width: 100vw; background-color: white; display:none; animation-name: none; animation-play-state: paused; animation-fill-mode: forwards; animation-duration: 1s; opacity: 0; } @keyframes appear { 0%{opacity: 0} 100%{opacity: 1} } @keyframes disappear { 0%{opacity: 1} 100%{opacity: 0} }
JavaScript(关键修改部分)
// 提前缓存DOM元素,避免重复查询DOM const overlay = document.getElementById("overlay"); const overlay2 = document.getElementById("overlay2"); function handleChange(checkbox) { if(checkbox.checked === true){ if (window.innerWidth < 846) { // 1. 重置动画状态:先清除之前的动画配置 overlay.style.animationName = "none"; // 强制浏览器重绘,确保样式重置生效(解决动画不触发的问题) void overlay.offsetWidth; // 2. 启动显示动画 overlay.style.display = "block"; overlay.style.animationName = "appear"; overlay.style.animationPlayState = "running"; overlay2.style.display = "none"; disableScroll(); } return false; }else{ // 3. 使用{ once: true },让事件监听器只触发一次后自动移除 overlay.addEventListener('animationend', () => { overlay.style.display = "none"; overlay2.style.display = "block"; }, { once: true }); // 启动隐藏动画 overlay.style.animationName = "disappear"; overlay.style.animationPlayState = "running"; enableScroll(); return false; } }
关键修改说明
- DOM元素缓存:把
overlay和overlay2提前获取,避免每次调用函数都重复查询DOM,既提升性能又让代码更简洁。 - 一次性事件监听:
{ once: true }选项会让animationend监听器在执行一次后自动被移除,彻底解决了监听器叠加导致的多次触发问题。 - 强制重绘:
void overlay.offsetWidth这行代码会强制浏览器立即应用之前的样式修改,确保我们重置动画状态后,新的appear动画能正常从头播放,不会被旧的动画状态干扰。 - 动画状态重置:显示遮罩前先把
animationName设为none,确保遮罩回到初始的opacity: 0状态,再播放appear动画,保证每次显示都是平滑的淡入效果。
内容的提问来源于stack exchange,提问作者Aleksandre Bregadze
相关产品推荐
相关产品推荐

