如何解决onkeydown实现角色WASD控制时移动几秒后停止的问题?
问题:键盘控制角色移动仅持续数毫秒就停止
我实现了鼠标控制角色移动的功能,但改用onkeydown替代onmousedown时,角色仅移动数毫秒就停止,松开按键后角色进入idle动画。请问该如何修复?
左右移动核心逻辑代码
const rightHandler = () => { heroImg.style.transform = "scale(1,1)"; direction = "right"; spritePosition = spritePosition + 1; imgBlockPosition = imgBlockPosition + 1; if (spritePosition > 7) { spritePosition = 0; } heroImg.style.left = `-${spritePosition * 64}px`; heroImg.style.top = '-64px'; imgBlock.style.left = `${imgBlockPosition * 7}px`; } const leftHandler = () => { heroImg.style.transform = "scale(-1,1)"; direction = "left"; spritePosition = spritePosition - 1; imgBlockPosition = imgBlockPosition - 1; if (spritePosition < 7) { spritePosition = 13; } heroImg.style.left = `-${spritePosition * 64}px`; heroImg.style.top = '-64px'; imgBlock.style.left = `${imgBlockPosition * 7}px`; }
正常工作的鼠标控制代码
let onMouseDown = (event) => { clearInterval(timer); x = event.screenX; timer = setInterval(() => { if (x > halfWidth) { direction = "right"; rightHandler(); } else { direction = "left"; leftHandler(); } }, 100); } let onMouseUp = (event) => { clearInterval(timer); idleAnimation(); }
存在问题的键盘控制代码
let onKeyDown = (event) => { clearInterval(timer); var keyCode = event.keyCode; timer = setInterval(() => { if (keyCode == 39) { direction = "right"; rightHandler(); } else if (keyCode == 37) { direction = "left"; leftHandler(); } }, 100); } let onKeyUp = () => { clearInterval(timer); idleAnimation(); }
修复方案
问题根源
按住键盘按键时,浏览器会先触发一次onkeydown,随后等待系统默认的按键重复延迟(通常几百毫秒)才会连续触发onkeydown事件。你的代码每次触发onkeydown都会执行clearInterval(timer),导致第一次创建的定时器被后续重复触发的onkeydown清空,角色因此停止移动。
修复代码(基础版)
新增一个状态变量标记是否正在移动,避免重复创建/清空定时器:
// 新增状态变量,标记当前是否处于移动状态 let isMoving = false; let onKeyDown = (event) => { // 如果已经在移动,直接返回,跳过后续逻辑 if (isMoving) return; clearInterval(timer); const keyCode = event.keyCode; isMoving = true; timer = setInterval(() => { if (keyCode === 39) { direction = "right"; rightHandler(); } else if (keyCode === 37) { direction = "left"; leftHandler(); } }, 100); } let onKeyUp = () => { clearInterval(timer); isMoving = false; // 重置移动状态 idleAnimation(); }
进阶优化方案(支持多按键同时按下)
如果需要支持多按键操作(比如同时按住左右键的逻辑处理),可以用集合记录当前按下的按键,定时器中检查按键状态:
// 用集合存储当前按下的按键码 const pressedKeys = new Set(); let timer = null; document.addEventListener('keydown', (event) => { pressedKeys.add(event.keyCode); // 仅当定时器未启动时创建 if (!timer) { timer = setInterval(() => { // 优先处理右键,可根据需求调整优先级 if (pressedKeys.has(39)) { direction = "right"; rightHandler(); } else if (pressedKeys.has(37)) { direction = "left"; leftHandler(); } }, 100); } }); document.addEventListener('keyup', (event) => { pressedKeys.delete(event.keyCode); // 没有按键按下时停止定时器 if (pressedKeys.size === 0) { clearInterval(timer); timer = null; idleAnimation(); } });
内容的提问来源于stack exchange,提问作者daniel vor
相关产品推荐
相关产品推荐

