使用setTimeout关闭带动画模态框后立即点击无法打开问题咨询
问题根因
- 定时器冲突:触发关闭模态框后,
setTimeout会在2秒后执行将模态框设为display: none的逻辑,若在这2秒内重新打开模态框,刚被设为display: initial的模态框会被后续触发的旧定时器回调再次设为隐藏,导致必须等定时器执行完毕才能正常打开。 - 透明元素拦截点击:淡出动画执行期间,模态框仅
opacity变为0,实际仍以最高层级悬浮在页面上方,会拦截所有下层元素的点击事件。你观察到的仅点击原图片区域可正常触发的现象,是因为该区域对应的slide仍绑定了点击关闭事件,点击后会二次触发关闭逻辑,其他区域的模态框背景无绑定事件,点击无响应。
修复方案
方案1:最小改动修复现有逻辑
- 新增全局定时器变量,打开模态框时清空未执行的关闭定时器,避免旧逻辑覆盖新操作:
// 全局新增 let closeTimer = null; // closeModal内修改setTimeout赋值 closeTimer = setTimeout( () => { $("#my_modal").style.display = "none"; for (let i = 0; i < slides.length; i++) { slides[i].style.display = "none"; } }, 1998); // openModal最开头新增清定时器逻辑 clearTimeout(closeTimer);
- 淡出时禁用模态框的点击响应,避免透明元素拦截下层点击:
// closeModal内设置fadeOut时新增 $(".fade").style.pointerEvents = "none"; // openModal内设置fadeIn时新增 $(".fade").style.pointerEvents = "auto";
方案2:更规范的动画实现(推荐)
用CSS Transition + transitionend事件替代Keyframe动画 + 固定时长setTimeout,逻辑更稳定,无定时器冲突问题:
- 替换CSS动画相关代码:
/* 删掉原有的fadeIn、fadeOut keyframe和animation-duration配置,替换为以下代码 */ .fade { transition: opacity 2s ease; opacity: 0; pointer-events: none; } .fade.active { opacity: 1; pointer-events: auto; }
- 重写开闭模态框的动画逻辑:
const closeModal = evt => { for ( let i in slides ) { if ( evt.target == slides[i] || evt.target == $("#close_button") ) { const fadeEl = $(".fade"); // 移除active类触发淡出 fadeEl.classList.remove("active"); // 监听过渡结束事件,执行关闭逻辑,仅触发一次 fadeEl.addEventListener("transitionend", () => { $("#my_modal").style.display = "none"; slides.forEach(slide => slide.style.display = "none"); }, { once: true }); // 原有其他逻辑不变:恢复滚动、恢复tab索引、暂停视频等 $("body").style.overflow = "initial"; for (let i = 0; i < gallery.length; i++) { gallery[i].setAttribute("tabindex", "1"); } const videos = $all(".video_slides video"); for (let p = 0; p < videos.length; p++) { videos[p].pause(); } } } } const openModal = evt => { for ( let i in gallery ) { if ( evt.currentTarget == gallery[i] ) { $("body").style.overflow = "hidden"; for (let t = 0; t < gallery.length; t++) { gallery[t].removeAttribute("tabindex"); } $("#my_modal").style.display = "initial"; // 下一帧添加active类,触发淡入动画 requestAnimationFrame(() => { $(".fade").classList.add("active"); }); slides[i].style.display = "initial"; slides[i].addEventListener("click", closeModal); } } }
内容的提问来源于stack exchange,提问作者Boros
相关产品推荐
相关产品推荐

