JavaScript Многократное нажатие клавиши EventListener прекращается после нажатия одной клавиши - PullRequest
1 голос
/ 27 апреля 2020

Доброе утро, у меня проблемы с EventListener. У меня есть событие нажатия клавиш, когда я проверяю, нажата ли одна или несколько клавиш.

Моя проблема: У меня есть три случая: (W + A) - (W + D) или W. После того, как я нажимаю W + A и отпускаю клавишу A, происходит событие keyup срабатывает. Таким образом, логически событие keydown останавливается, но чтобы снова запустить событие keydown, мне нужно отпустить W и снова нажать его. Даже если клавиша W еще не нажата после нажатия клавиши A, событие нажатия клавиши не начнется снова.

Мой вопрос: Есть ли способ запустить событие, настроив Событие keydown для true или . Существует ли способ, при котором событие keydown распознает нажатую клавишу, не нажимая ее снова.

Событие 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 }
        });

Надеюсь, кто-нибудь сможет мне помочь. Заранее спасибо

1 Ответ

1 голос
/ 27 апреля 2020

Резервное копирование событий, если не невозможно, но чрезвычайно сложно и требует много времени. Вместо этого зарегистрируйте ключевые события отдельно, создайте «main l oop» для чтения реестра (и для выполнения других действий). Приведенный ниже фрагмент не является прямым решением, встроенным в ваш код, вместо этого он представляет реестр клавиш и основной l oop в простом примере того, как управлять элементом на экране.

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 (конечно, это может быть отдельный объект). Свойства в реестре именуются используемыми ключами. Удары клавиш и релизы прослушиваются независимо от основного l oop, а реестр ключей постоянно обновляется с помощью прослушивателя этих двух событий.

...