jQuery keydown函数重复触发:按住按键时动画叠加问题求助
解决jQuery按键触发动画叠加的问题
这个问题我之前做小游戏的时候也踩过坑!核心原因就是浏览器的按键重复触发机制——按住按键时keydown会每隔几十毫秒就触发一次,每次触发都会给元素塞一个新的动画到队列里,结果就是动画越堆越多,元素动得乱七八糟。下面给你几个实用的解决办法,你可以根据自己的需求选:
方法一:用状态锁阻止重复触发
设置一个变量标记当前是否正在执行动画,只有上一轮动画完全结束后,才允许响应下一次按键。这个方法能严格保证动画的执行顺序,不会出现“插队”的情况:
// 定义全局状态变量,标记是否正在执行动画 let isAnimating = false; $("body").keydown(function (Taste) { // 如果当前有动画在执行,直接跳过这次触发 if (isAnimating) return; var figPosNow = $("#figur").css("top"); var figPosNowInt = parseInt(figPosNow); var changePos = 0; if (Taste.keyCode == 38) { changePos -= 100; Taste.preventDefault(); } var newFigPos = (figPosNowInt + changePos) + "px"; // 开始动画前“上锁” isAnimating = true; $("#figur") .animate({top: newFigPos}, 200) .animate({top: figPosNow}, 200, function() { // 所有动画完成后“解锁” isAnimating = false; }); });
方法二:用stop()清空动画队列
每次触发按键时,先停止元素当前的所有动画并清空待执行的动画队列,再执行新的动画。这种方法更直接,适合不需要严格等待上一轮动画结束的场景:
$("body").keydown(function (Taste) { var figPosNow = $("#figur").css("top"); var figPosNowInt = parseInt(figPosNow); var changePos = 0; if (Taste.keyCode == 38) { changePos -= 100; Taste.preventDefault(); } var newFigPos = (figPosNowInt + changePos) + "px"; // stop(true, false):清空动画队列,且当前动画停在当前位置 $("#figur") .stop(true, false) .animate({top: newFigPos}, 200) .animate({top: figPosNow}, 200); });
小提示:
stop()的两个参数可以调整:第一个true表示清空所有待执行的动画队列,第二个参数如果设为true,会让元素直接跳到当前动画的目标位置再执行新动画,你可以根据自己的视觉需求调整。
方法三:结合keydown和keyup实现按住持续动画
如果你的需求是按住上键时元素持续重复动画,松开就停止,那上面的方法可能不够。这时候可以用定时器来控制,keydown时启动定时器,keyup时清除定时器,确保动画按固定间隔执行,不会叠加:
let animationTimer = null; $("body").keydown(function (Taste) { if (Taste.keyCode != 38) return; Taste.preventDefault(); // 如果定时器已存在,说明正在持续触发,直接返回 if (animationTimer) return; // 定时器间隔设为动画总时长(200+200),确保上一轮结束再执行下一轮 animationTimer = setInterval(function() { var figPosNow = $("#figur").css("top"); var figPosNowInt = parseInt(figPosNow); var newFigPos = (figPosNowInt - 100) + "px"; $("#figur") .animate({top: newFigPos}, 200) .animate({top: figPosNow}, 200); }, 400); }); $("body").keyup(function (Taste) { if (Taste.keyCode == 38) { // 松开按键时清除定时器 clearInterval(animationTimer); animationTimer = null; } });
内容的提问来源于stack exchange,提问作者jkresse
相关产品推荐
相关产品推荐

