JavaScript EventListener 在一键触发 keyup 后停止多次 keydown

JavaScript EventListener multiple keydown stops after one key triggers keyup

早上好,我遇到了 EventListener 的问题。我有一个 keydown 事件,我在其中检查是否按下了多个键或单击了一次。

我的问题: 我有三种情况:(W + A) - (W + D) 或 W。在我按下 W + A 并释放 A 键后,触发了 keyup 事件。所以从逻辑上讲,keydown 事件已停止,但要重新启动 keydown 事件,我必须释放 W 并再次按下它。即使在 A 键按下后 W 键仍然按下,keydown 事件也不会再次启动。

我的问题: 有没有一种方法可以通过将 keydown 事件设置为 true 来启动事件备份有没有一种方法可以让 keydown 事件识别一个仍然按下的键而无需再次按下它。

按键事件:

        document.addEventListener("keydown", event => {
            if (!keyStatus) { keyStatus = keyDown(event); }
            if (Object.keys(keysDown).length < 2) {
                keysDown = (keysDown || []);
            } else { Object.keys(keysDown).forEach(k => delete keysDown[k]); }
            keysDown[event.keyCode] = true;
            switch (true) {
                case keysDown[65] && keysDown[87]:
                    if (currentCode.includes(68) || (currentCode.length <= 1 && currentCode.includes(87))) { currentCode = [] }
                    if (currentCode.includes(65) && currentCode.includes(87)) {
                        break;
                    } else { currentCode.push(65, 87); }
                    multiStatus = true
                    break;
                case keysDown[68] && keysDown[87]:
                    if (currentCode.includes(65) || (currentCode.length <= 1 && currentCode.includes(87))) { currentCode = [] }
                    if (currentCode.includes(68) && currentCode.includes(87)) {
                        break;
                    } else { currentCode.push(68, 87) }
                    multiStatus = true
                    break;
                case keysDown[87] && !multiStatus:
                    if (currentCode.includes(65) || currentCode.includes(68)) { currentCode = [] }
                    if (currentCode.length <= 1 && currentCode.includes(87)) {
                        break;
                    } else { currentCode.push(87) }
                    break;
                default:
                    multiStatus = false
                    break;
            }
        });
        document.addEventListener("keyup", event => {
            if (keyStatus) { keyStatus = keyUp(event); currentCode = []; multiStatus = false }
        });

我希望有人能够帮助我。提前致谢

备份事件即使不是不可能,但也非常困难和耗时。相反,单独注册键事件,创建一个 "main loop" 用于读取注册表(以及执行其他操作)。下面的代码片段不是适合您的代码的直接解决方案,而是在如何控制屏幕上的元素的简单示例中介绍了按键注册表和主循环。

const ball = {
  a: 0,
  d: 0,
  w: 0,
  z: 0,
  speed: 2,
  posX: 0,
  posY: 0,
  el: document.querySelector('.ball')
}

function regKeyStrokes(e) {
  if (!'adwz'.includes(e.key)) {return;}
  ball[e.key] = (event.type === 'keyup') ? 0 : 1;
}

function animate() {
  const dX = ball.a * -ball.speed + ball.d * ball.speed;
  const dY = ball.w * -ball.speed + ball.z * ball.speed;
  const cS = (dX * dY === 0) ? 1 : 0.707;
  ball.posX += cS * dX;
  ball.posY += cS * dY;
  ball.el.style.transform = `translate(${ball.posX}px, ${ball.posY}px)`;
  requestAnimationFrame(animate);
}

document.addEventListener('keyup', regKeyStrokes);
document.addEventListener('keydown', regKeyStrokes);

requestAnimationFrame(animate);
.ball {
   position: fixed;
   width: 50px;
   height: 50px;
   background: red;
   border-radius: 100%;
}
<div class="ball"></div>

在代码片段中,密钥注册表是 ball 对象的一部分(这当然可以是一个单独的对象)。寄存器中的属性由使用的键命名。键击和释放独立于主循环进行监听,键注册表与这两个事件的监听器保持同步。