Challenger5 Challenger5 - 1 month ago 14
Javascript Question

JavaScript - Detecting Key Presses

I am using addEventListener to check the user's keypresses,
but there are some problems.

This is my code:

// get key presses

var keys = {
up: false,
down: false,
left: false,
right: false
}

function keyUpdate(keyEvent, down) {
// down is a boolean, whether the key event is keydown (true) or keyup (false)
switch (keyEvent.keyCode) {

case 38:
keys.up = down;
break;

case 40:
keys.down = down;
break;

case 37:
keys.left = down;
break;

case 39:
keys.right = down;
break;
}
}

document.addEventListener("keydown", function(event) {
keyUpdate(event, true);
});

document.addEventListener("keyup", function(event) {
keyUpdate(event, false);
});


This code has two problems:


  • It doesn't seem to let more than 2 keys be active at once

  • It seems to constantly update the
    keys
    variables when it should only be
    updating it when a key is first pressed or released. This might be a
    performance issue, but it's not that important.



Why do I have these problems?

EDIT: Looking at the answers, I have come to the conclusion that it is a problem with my browser/computer. It seems to only happen with the arrow keys. As mobius said, it is really not necessary for more than two keys to be active at once.

Answer

I am able to get at two keys to show at once with the code you provided. I have modified the example to display the data, and a graphical representation. If you are not seeing multiple keys work at once, it is probably a browser limitation.

I am using Chrome 53 on OSX

// get key presses

var keys = {
  up: false,
  down: false,
  left: false,
  right: false
}

function keyUpdate(keyEvent, down) {
  // down is a boolean, whether the key event is keydown (true) or keyup (false)
  keyEvent.preventDefault(); // prevent screen from going crazy while i press keys.
  console.log(keyEvent.keyCode)
  switch (keyEvent.keyCode) {

    case 87: // W key.
    case 38:  // up key.
      keys.up = down;
      var key = document.querySelector('.up');
      if (down){
        key.classList.add('pressed');
      } else {
        key.classList.remove('pressed');
      }
      break;
      
    case 83: // S key
    case 40: // down key
      keys.down = down;
      var key = document.querySelector('.down');
      if (down){
        key.classList.add('pressed');
      } else {
        key.classList.remove('pressed');
      }
      break;

    case 65: // A key
    case 37: // left arrow.
      keys.left = down;
      var key = document.querySelector('.left');
      if (down){
        key.classList.add('pressed');
      } else {
        key.classList.remove('pressed');
      }
      break;
    case 68:
    case 39: // right arrow.
      keys.right = down;
      var key = document.querySelector('.right');
      if (down){
        key.classList.add('pressed');
      } else {
        key.classList.remove('pressed');
      }
      break;
    default:
      if (down){
         keys[keyEvent.keyCode] = down;
      } else if (keyEvent.keyCode in keys){
        delete keys[keyEvent.keyCode];
      }
  }
  var text = JSON.stringify(keys, null, 4);
  document.querySelector('.code').innerHTML = text;
}

document.addEventListener("keydown", function(event) {
  keyUpdate(event, true);
});

document.addEventListener("keyup", function(event) {
  keyUpdate(event, false);
});


document.querySelector('.code').innerHTML = JSON.stringify(keys, null, 4);
h3 {
  text-align: center;
  font-family: sans-serif;
  text-decoration: underline;
  font-weight: normal;
}
.keys {
  width: 150px;
  margin: 0 auto;
}
.rows {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items : center;
}

.key{
  flex: 1;
  width: 50px;
  max-width: 50px;
  height: 50px;
  background-color: #eee;
  text-align:center;
  line-height: 50px;
  border-radius: 3px;
  border: 1px solid #aaa;
  transition: all .2s ease;
  color : #555;
  font-size: 20px;
  font-weight: bold;
}

.pressed{
  color : #ddd;
  background-color: #aaa;
  border: 1px solid #eee;
}

.columns{
  display: flex;
  flex-direction: row;
  justify-content: space-arround;
}

.code {
  background-color: #efefef;
  border: 1px solid #aaa;
}
<h3> click here to start capturing keyboard input</h1>
<div class="keys rows">
  <div class="key up">↑</div>
  <div class="columns">
    <div class="key left">←</div>
        <div class="key down">↓</div>
    <div class="key right">→</div>
  </div>
</div>
<pre class="code">
</pre>

EDIT: on further inspection the restriction to only two keys at once seems to be limited to arrow keys. I have updated the example to show any currently pressed keys by key code in addition to arrow keys. You will notice that you can add more than two.

edit 2 I use the dvorak keyboard layout, and didn't realize that I had set the WASD keys wrong. They are now correct for standard QWERTY layouts.