简体   繁体   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?

I am making a frogger replica and I want the frog to move only once when I press a key, basically to prevent it from moving multiple times if a key is held down.我正在制作一个青蛙复制品,我希望青蛙在我按下一个键时只移动一次,基本上是为了防止它在按住一个键时移动多次。

This is the relevant part of my code that handles the keydown event:这是我处理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; }
};

Update:更新:

I got it to not move when holding down keys, but now it won't let me move right after I moved right once, but will reset if I click another button, then does the same thing again:我让它在按住键时不移动,但现在它不会让我在我向右移动一次后立即移动,但如果我单击另一个按钮会重置,然后再次执行相同的操作:

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

You can use the KeyboardEvent.repeat property ( e.repeat ) to check if the user is just holding down the key and do nothing in that case.您可以使用KeyboardEvent.repeat属性 ( e.repeat ) 来检查用户是否只是按住键而在这种情况下什么也不做。

Basically, your code should look like this:基本上,您的代码应如下所示:

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;

Also, KeyboardEvent.which and KeyboardEvent.keyCode are both deprecated, as stated in the docs:此外, KeyboardEvent.whichKeyboardEvent.keyCode都已弃用,如文档中所述:

Deprecated已弃用

This feature is no longer recommended.不再推荐此功能。 Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes.尽管某些浏览器可能仍然支持它,但它可能已经从相关的 web 标准中删除,可能正在被删除,或者可能仅出于兼容性目的而保留。 Avoid using it, and update existing code if possible;避免使用它,并尽可能更新现有代码; see the compatibility table at the bottom of this page to guide your decision.请参阅本页底部的兼容性表以指导您的决定。 Be aware that this feature may cease to work at any time.请注意,此功能可能随时停止工作。

You should be using KeyboardEvent.key instead:您应该改用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; }

Note that in your updated code you are not validating that the frog is inside the canvas and you are defining the onkeydown listener inside the rendering function.请注意,在您更新的代码中,您没有验证青蛙是否在 canvas 内,并且您正在渲染 function 内定义onkeydown侦听器。 You should validate that and define the even listener only once, outside:您应该验证这一点并在外部仅定义一次偶数侦听器:

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

The keyboard driver will normally fire repeated keystrokes, which turn into distinct keypress events.键盘驱动程序通常会触发重复的击键,这会变成不同的按键事件。 Using this facility is generally not what you want for gaming, however, as the repeat delay is annoying, and both the repeat and initial repeat delay are OS-wide user preferences.但是,使用此功能通常不是您想要的游戏,因为重复延迟很烦人,并且重复和初始重复延迟都是操作系统范围内的用户偏好。

Instead, you should trap the keydown and keyup events.相反,您应该捕获 keydown 和 keyup 事件。 When the key goes down, use setInterval or setTimeout to trigger a reiteration timer and event.当按键按下时,使用 setInterval 或 setTimeout 触发重复计时器和事件。 When the key goes up, cancel the timer.当键上升时,取消定时器。

My preference would be use setTimeout, in case you miss the keyup event due to something like the user minimizing his window with the mouse while holding down the key.我的首选是使用 setTimeout,以防您因为用户在按住键的同时用鼠标最小化他的 window 之类的事情而错过了 keyup 事件。

I did what the one guy said(great advice btw, i'm glad you told me),but when i press an arrow, the shape disappears.我做了那个人说的(顺便说一句很好的建议,我很高兴你告诉我),但是当我按下箭头时,形状消失了。


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.

相关问题 当按住箭头键时,如何在Firefox中获得自动重复的keydown事件? - How can I get auto-repeated keydown events in Firefox when arrow keys are held down? 跨浏览器的方式,在按住键时自动重复重复按下事件 - Cross-browser way to get automatically repeating keydown events when key is held down 如何使用 JavaScript 同时传递两个按键事件? - How can I pass two keydown events at the same time with JavaScript? Javascript,如何让向上键只按一次 - Javascript, how do I make the up key only pressed once Javascript:限制按下按键事件监听器在按下时可以多快调用一次函数 - Javascript: Limit how quickly a keydown event listener can call a function when held down jQuery使用keydown / keyup / keypress事件仅触发一次,而不是按住键时触发多次 - jQuery using keydown/keyup/keypress event to fire only one time instead of multiple times when key held down 如何避免 JavaScript 中自动重复的 keydown 事件? - How can I avoid autorepeated keydown events in JavaScript? 当您想将重复的按键按下消息与javascript一起使用时,如果您按住按键但只想播放一次,该如何避免重复的按键按下消息? - How do you circumvent repeated keydown messages when you want to use them with javascript where you hold the key down but want it only to play once? 仅在按下键时如何更改值? - How do I change a value only when a key is pressed down? 如何在不捕获keydown事件的情况下查看修改键是否被按下? - How to see if a modifier key is being held down without catching the keydown event?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM