Search code examples
javascriptkeypressaddeventlistener

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.


Solution

  • 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.