当用户更改选项卡并返回时,停止触发事件侦听器

时间:2019-05-20 01:23:33

标签: javascript addeventlistener

我正在用JavaScript制作游戏,其中玩家是由箭头键控制的。

如果用户按下箭头键并同时更改选项卡,则当他们返回到选项卡时,由于事件监听器触发keydown而未通知keyup,因此播放器仍在移动。用户已更改标签。

在用户切换标签并返回后,我如何能够停止触发事件?

换句话说,我如何确保在用户切换选项卡并返回后,播放器不会根据先前按住的箭头键移动?

这里是我用来说明问题的示例:https://jsfiddle.net/mgh38d1e/

var canvas = document.getElementById('game');
var ctx = canvas.getContext('2d');

var player = {x: 0, y: 0};

function loop() {
  // draw background
	ctx.fillStyle = 'blue';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  
  // draw player
	ctx.fillStyle = 'lawngreen';
  ctx.fillRect(player.x, player.y, 50, 50);
  
  if(right) player.x += 1;
  
  requestAnimationFrame(loop);
}

loop();

var right = false;

addEventListener('keydown', function(e) {
	if(e.key == 'd')
  	right = true;
});

addEventListener('keyup', function(e) {
	if(e.key == 'd')
  	right = false;
});
<h1>Press D to move right</h1>
<canvas id="game" width="600" height="300"></canvas>

1 个答案:

答案 0 :(得分:1)

这就是我要记住的事情。

function byId(id) {
  return document.getElementById(id)
}

function newEl(tag) {
  return document.createElement(tag)
}

function qsa(sel, par = document) {
  return par.querySelectorAll(sel)
}
window.addEventListener('load', onLoaded, false);

class kbKey {
  constructor(name, keyCode) {
    this.name = name;
    this.keyCode = keyCode;
    return this;
  }
}

var keys = [];

var arrowKeys = [
  [null, new kbKey('^', 38), null],
  [new kbKey('<', 37), new kbKey('V', 40), new kbKey('>', 39), ]
];

var numPad = [
  [new kbKey('7', 103), new kbKey('8', 104), new kbKey('9', 105)],
  [new kbKey('4', 100), new kbKey('5', 101), new kbKey('6', 102)],
  [new kbKey('1', 97), new kbKey('2', 98), new kbKey('3', 99)],
  [new kbKey('>', 39), new kbKey('0', 96), new kbKey('.', 110)]
];

function onLoaded(evt) {
  window.addEventListener('keydown', onkeydown, false);
  window.addEventListener('keyup', onkeyup, false);

  window.addEventListener('focus', onFocus, false);
  window.addEventListener('blur', onBlur, false);

  keys = keys.fill(false);

  drawKeys(numPad);
}

function onkeydown(evt) {
  keys[evt.keyCode] = true;
  //	console.log(evt.key, evt.which);
  updateDisplay();
}

function onkeyup(evt) {
  keys[evt.keyCode] = false;
  updateDisplay();
}

function onBlur(evt) {
  keys = keys.fill(false);
}

function onFocus(evt) {
  updateDisplay();
}

function updateDisplay() {
  let cells = Array.from(qsa('#keyboard td'));

  cells.forEach(
    function(cell, index, collection) {
      if (cell.dataset.code != undefined) {
        if (keys[parseInt(cell.dataset.code)] == true)
          cell.classList.add('active');
        else
          cell.classList.remove('active');
      }
    }
  );
}

function drawKeys(keydata2D) {
  let tbl = byId('keyboard');

  keydata2D.forEach(function(rowArray, rowIndex, rowCollection) {
    let tr = newEl('tr');

    rowArray.forEach(
      function(key, col, keyArray) {
        let td = newEl('td');
        tr.appendChild(td);
        if (key != null) {
          td.textContent = key.name;
          td.dataset.code = key.keyCode;
        }
      }
    );
    tbl.appendChild(tr);
  });
}
td[data-code] {
  border: solid 1px gray;
}

.active {
  background-color: #ffad68;
}
<table id='keyboard'></table>