You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS动画重复触发崩溃求助:复选框控制遮罩层显隐动画异常

解决遮罩层动画重复操作崩溃的问题

嘿,我一眼就发现问题所在了——你第二次勾选复选框时动画崩溃,核心原因是重复绑定了animationend事件,加上动画状态没有正确重置,导致后续的动画逻辑混乱。咱们一步步来修复:

问题诊断

  1. 事件监听叠加:每次取消勾选时,你都会给overlay添加一个新的animationend监听器,但从未移除旧的。第二次取消操作后,监听器会叠加,动画结束时会多次执行隐藏逻辑,甚至和新的显示操作冲突。
  2. 动画状态残留:再次勾选显示遮罩时,之前的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 20:32:31