Вы можете использовать свойство 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.which
и KeyboardEvent.keyCode
устарели, как указано в документах:
устарел
Эта функция больше не рекомендуется. Хотя некоторые браузеры могут по-прежнему поддерживать его, он, возможно, уже удален из соответствующих веб-стандартов, может быть в процессе удаления или может храниться только в целях совместимости. Избегайте его использования и обновляйте существующий код, если это возможно; см. таблицу совместимости внизу этой страницы, чтобы принять решение. Имейте в виду, что эта функция может перестать работать в любой момент.
Вместо этого следует использовать 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;
}
Обратите внимание, что в обновленном коде вы не проверяете, что лягушка находится внутри холста, и вы определяете прослушиватель 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" />