JavaScript - 检测按键

时间:2016-10-24 18:04:03

标签: javascript keypress addeventlistener

我正在使用addEventListener来检查用户的按键, 但是有一些问题。

这是我的代码:

// 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);
});

此代码有两个问题:

  • 似乎不会让超过2个键同时处于活动状态
  • 它应该只在不断更新keys变量时 首次按下或释放按键时更新它。这可能是一个 性能问题,但并不重要。

为什么我会遇到这些问题?

编辑:看看答案,我得出的结论是我的浏览器/电脑存在问题。它似乎只发生在箭头键上。正如莫比乌斯所说,实际上没有必要同时激活两个以上的密钥。

2 个答案:

答案 0 :(得分:2)

我可以使用您提供的代码同时显示两个键。我修改了示例以显示数据和图形表示。如果您没有看到多个密钥同时工作,则可能是浏览器限制。

我在OSX上使用Chrome 53

// 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>

编辑:在进一步检查时,对一次只有两个键的限制似乎仅限于箭头键。我已经更新了示例,除了箭头键之外,还通过键代码显示当前按下的任何键。您会注意到可以添加两个以上。

编辑2 我使用了dvorak键盘布局,并没有意识到我设置了错误的WASD键。它们现在对于标准QWERTY布局是正确的。

答案 1 :(得分:1)

使用按键事件,以便仅在用户按下某个键时执行,而不是在按下时执行。

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

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