[英]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.which
和KeyboardEvent.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.