如何避免JavaScript keydown事件在动画未完成时重复触发?
解决键盘快速连续触发导致动画异常的问题
你遇到的是典型的重复触发异步操作导致的动画堆积问题,核心思路是给上下滑动的操作分别加「执行锁」,在当前动画未完成前,拒绝同方向的下一次触发。具体实现步骤如下:
实现方案
- 定义两个状态变量作为执行锁,分别控制上下滑动的触发权限
- 在
slideDown()和slideUp()内部先检查锁状态:如果当前正在执行对应动画,直接返回;否则锁定并执行动画,动画结束后解锁 - 事件监听逻辑保持原有判断,但依赖加锁后的滑动函数
修改后的完整代码
// 初始化执行锁,默认未锁定 let isSlidingDown = false; let isSlidingUp = false; function slideDown() { // 如果正在执行下滑动画,直接返回 if (isSlidingDown) return; // 锁定下滑操作 isSlidingDown = true; // 这里是你的下滑动画逻辑,比如DOM操作、CSS过渡等 // 示例:假设动画时长为300ms,动画结束后解锁 // 如果是用CSS transition/animation,建议监听transitionend/animationend事件来解锁 setTimeout(() => { // 动画完成后解锁 isSlidingDown = false; }, 300); } function slideUp() { // 如果正在执行上滑动画,直接返回 if (isSlidingUp) return; // 锁定上滑操作 isSlidingUp = true; // 你的上滑动画逻辑 setTimeout(() => { // 动画完成后解锁 isSlidingUp = false; }, 300); } window.addEventListener("keydown", (e) => { if (e.key === "ArrowDown") slideDown(); if (e.key === "ArrowUp") slideUp(); myName.style.color = counter === 3 ? "white" : "black"; })
关键细节说明
- 如果你用的是CSS过渡/动画,不要用
setTimeout来解锁,应该监听元素的transitionend或animationend事件,确保动画真正结束后才解锁,比如:function slideDown() { if (isSlidingDown) return; isSlidingDown = true; // 执行动画操作,比如添加类名 targetElement.classList.add("slide-down"); // 监听动画结束事件({ once: true }确保事件只触发一次) targetElement.addEventListener("transitionend", function unlock() { isSlidingDown = false; targetElement.classList.remove("slide-down"); targetElement.removeEventListener("transitionend", unlock); }, { once: true }); } - 锁变量分开控制上下方向,不会影响相反方向的操作;如果需要完全禁止所有操作,可以合并成一个全局锁变量
内容的提问来源于stack exchange,提问作者Abdel Rahman Yosry
相关产品推荐
相关产品推荐

