How to store simultaneous keypresses

51 views Asked by At

When I use the key-up event listener in JavaScript, the keys "wait" before starting again. I think it's because the key-up needs to listen to specific keys but for me that hasn't worked yet.

I have tried using different tutorials for different perspectives on this problem, but none of them have worked for me yet... I think I just need to not use the key-up event listener but I'm not sure how. I only have only known JavaScript for a few weeks so I don't know how to use advanced methods for things.

var key = "";
document.addEventListener('keyup', e => { key = ""; });
document.addEventListener('keydown', e => { key = e.code; });
setInterval(e => {
    document.getElementById('test').innerText = key;
}, Infinity);
<p>Press and hold keys...</p>
<p id="test"></p>
If you were to press A, then press D right afterward, it would wait a bit before saying D is pressed. That is a problem because I'm trying to be able to make a gamepad for pressing multiple keys at once.

1

There are 1 answers

2
Gershom Maes On BEST ANSWER

Use a Set (mdn reference) to track all keys currently pressed. Your current approach of using a single string, key, is impractical for storing multiple keys.

const codes = new Set();

const updateDisplay = (mode, evt) => {
  evt.preventDefault();
  if (mode === 'add') codes.add(evt.code);
  if (mode === 'rem') codes.delete(evt.code);
  document.querySelector('.state').textContent = [ ...codes ].join(' + ') || '(no keys)';
}

window.addEventListener('keydown', evt => updateDisplay('add', evt));
window.addEventListener('keyup', evt => updateDisplay('rem', evt));

window.addEventListener('focus', () => document.querySelector('.focus').style.display = 'none');
window.addEventListener('blur', () => document.querySelector('.focus').style.display = '');
<div class="focus">WINDOW IS UNFOCUSED; CANNOT PROCESS KEY EVENTS (please click)</div>
<p>Press and release buttons (potentially many at once)</p>
<p>Current state: <span class="state">(no keys)</span></p>