簡體   English   中英

使用 JavaScript 每次按下鍵時,即使它被按住,我如何才能只獲取一次 keydown 事件?

[英]How can I get keydown events only once each time the key is pressed, even if it's held down, with JavaScript?

我正在制作一個青蛙復制品,我希望青蛙在我按下一個鍵時只移動一次,基本上是為了防止它在按住一個鍵時移動多次。

這是我處理keydown事件的代碼的相關部分:

document.onkeydown = function(e) {
  var key = e.which || e.keyCode;

  if (key == 37){ frog.x = frog.x - 50; }
  if (key == 38){ frog.y = frog.y - 50; }
  if (key == 39){ frog.x = frog.x + 50; }
  if (key == 40){ frog.y = frog.y + 50; }
};

更新:

我讓它在按住鍵時不移動,但現在它不會讓我在我向右移動一次后立即移動,但如果我單擊另一個按鈕會重置,然后再次執行相同的操作:

 const canvas = document.getElementById('canvas'); const c = canvas.getContext('2d'); canvas.height = window.innerHeight; canvas.width = window.innerWidth; let frog = { x: 0, y: 0, fw: 50, fh: 50, fmx: 0, fmy: 0, }; let counter = 0; function animate() { requestAnimationFrame(animate); // Clear previous scene: c.clearRect(0, 0, window.innerWidth, window.innerHeight); // Draw frog: c.fillStyle = '#000' c.fillRect(frog.x, frog.y, frog.fw, frog.fh); // Movement of the frog with keys: document.onkeydown = function(e) { e = e || window.event; var key = e.which || e.keyCode; if (key == 65 && counter === 0) { frog.x = frog.x - 50, counter = 1 } if (key == 87 && counter === 0) { frog.y = frog.y - 50, counter = 1 } if (key == 68 && counter === 0) { frog.x = frog.x + 50, counter = 1 } if (key == 83 && counter === 0) { frog.y = frog.y + 50, counter = 1 } }; document.onkeyup = function(e) { e = e || window.event; var key = e.which || e.keyCode; if (key == 65) { counter = 0 } if (key == 87) { counter = 0 } if (key == 68) { coutner = 0 } if (key == 83) { counter = 0 } }; } animate();
 body { margin: 0; } #canvas { width: 100%; height: 100%; }
 <canvas id="canvas" />

您可以使用KeyboardEvent.repeat屬性 ( e.repeat ) 來檢查用戶是否只是按住鍵而在這種情況下什么也不做。

基本上,您的代碼應如下所示:

if (e.repeat) return; // Do nothing

const key = e.which || e.keyCode;

if (key === 37) frog.x = frog.x - 50;
else if (key === 38) frog.y = frog.y - 50;
else if (key === 39) frog.x = frog.x + 50;
else if (key === 40) frog.y = frog.y + 50;

此外, KeyboardEvent.whichKeyboardEvent.keyCode都已棄用,如文檔中所述:

已棄用

不再推薦此功能。 盡管某些瀏覽器可能仍然支持它,但它可能已經從相關的 web 標准中刪除,可能正在被刪除,或者可能僅出於兼容性目的而保留。 避免使用它,並盡可能更新現有代碼; 請參閱本頁底部的兼容性表以指導您的決定。 請注意,此功能可能隨時停止工作。

您應該改用KeyboardEvent.key

 const frog = { x: 500, y: 500 }; document.addEventListener('keydown', (e) => { e.preventDefault(); if (e.repeat) return; // Do nothing const { key } = e; switch(key) { case 'ArrowUp': frog.y = frog.y - 50; break; case 'ArrowRight': frog.x = frog.x + 50; break; case 'ArrowDown': frog.y = frog.y + 50; break; case 'ArrowLeft': frog.x = frog.x - 50; break; } if (key.startsWith('Arrow')) console.log(frog); });
 .as-console-wrapper { max-height: 100%;important; }

請注意,在您更新的代碼中,您沒有驗證青蛙是否在 canvas 內,並且您正在渲染 function 內定義onkeydown偵聽器。 您應該驗證這一點並在外部僅定義一次偶數偵聽器:

 const frog = { x: 0, y: 0, fw: 50, fh: 50, }; const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const MAX_X = window.innerWidth - frog.fw; const MAX_Y = window.innerHeight - frog.fh; canvas.width = window.innerWidth; canvas.height = window.innerHeight; function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = '#000'; ctx.fillRect(frog.x, frog.y, frog.fw, frog.fh); requestAnimationFrame(animate); } // This should be declared outside the rendering function: document.onkeydown = (e) => { e.preventDefault(); if (e.repeat) return; // Do nothing const { key } = e; switch(key) { case 'ArrowUp': frog.y = Math.max(0, frog.y - 50); break; case 'ArrowRight': frog.x = Math.min(frog.x + 50, MAX_X); break; case 'ArrowDown': frog.y = Math.min(frog.y + 50, MAX_Y); break; case 'ArrowLeft': frog.x = Math.max(0, frog.x - 50); break; } }; requestAnimationFrame(animate);
 body { margin: 0; } #canvas { width: 100%; height: 100%; }
 <canvas id="canvas" />

鍵盤驅動程序通常會觸發重復的擊鍵,這會變成不同的按鍵事件。 但是,使用此功能通常不是您想要的游戲,因為重復延遲很煩人,並且重復和初始重復延遲都是操作系統范圍內的用戶偏好。

相反,您應該捕獲 keydown 和 keyup 事件。 當按鍵按下時,使用 setInterval 或 setTimeout 觸發重復計時器和事件。 當鍵上升時,取消定時器。

我的首選是使用 setTimeout,以防您因為用戶在按住鍵的同時用鼠標最小化他的 window 之類的事情而錯過了 keyup 事件。

我做了那個人說的(順便說一句很好的建議,我很高興你告訴我),但是當我按下箭頭時,形狀消失了。


canvas.height = window.innerHeight;
canvas.width = window.innerWidth;

//variables

let frog = {
    x: 500,
    y: 500,
    fw: 50,
    fh: 50,
    fmx: 0,
    fmy: 0
}

//running it all

function animate(){
    requestAnimationFrame(animate)
    c.clearRect(0,0,innerWidth,innerHeight)

    //frog
    c.fillStyle = '#000'
    c.fillRect(frog.x,frog.y,frog.fw,frog.fh)


document.addEventListener('keydown', (e) => {
  e.preventDefault();

  if (e.repeat) return; // Do nothing

  const { key } = e;

  switch(key) {
    case 'ArrowUp':
      frog.y = frog.y - 50;
      break;

    case 'ArrowRight':
      frog.x = frog.x + 50;
      break;

    case 'ArrowDown':
      frog.y = frog.y + 50;
      break;

    case 'ArrowLeft':
      frog.x = frog.x - 50;
      break;  
  }
  if (key.startsWith('Arrow')) console.log(frog);
});

}

animate();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM