Одно из возможных решений: вы можете отслеживать, какие ходы были запрошены, и ждать, пока не завершится предыдущий ход. Пример:
const box = document.getElementsByClassName('box')[0];
const startValue = '0px';
const shiftValue = '400px';
function moveDown() {
// The move* functions only perform the move if is valid - i.e.,
// if it would actually cause a visible change.
if (box.style.marginTop !== shiftValue) {
box.style.marginTop = shiftValue;
return true;
}
// The move* functions return true iff the move was made.
return false;
}
function moveRight() {
if (box.style.marginLeft !== shiftValue) {
box.style.marginLeft = shiftValue;
return true;
}
return false;
}
function moveUp() {
if (box.style.marginTop !== startValue) {
box.style.marginTop = startValue;
return true;
}
return false;
}
function moveLeft() {
if (box.style.marginLeft !== startValue) {
box.style.marginLeft = startValue;
return true;
}
return false;
}
const moves = [];
let timeOfLastMoveInMilliseconds = null;
const animationDurationInSeconds = 0.5; // should match css transition duration
const animationDurationInMilliseconds = animationDurationInSeconds * 1000;
function onFrame() {
if (!timeOfLastMoveInMilliseconds) {
timeOfLastMoveInMilliseconds = performance.now();
}
const timeSinceLastMove = performance.now() - timeOfLastMoveInMilliseconds;
if (moves.length > 0 && timeSinceLastMove >= animationDurationInMilliseconds) {
const wasMoved = moves.pop()();
if (wasMoved) {
timeOfLastMoveInMilliseconds = performance.now();
}
}
window.requestAnimationFrame(onFrame);
}
window.requestAnimationFrame(onFrame);
document.addEventListener('keydown', function({keyCode, which}) {
const keycode = keyCode ? keyCode : which;
switch(keycode) {
case(40):
moves.unshift(moveDown);
break;
case(39):
moves.unshift(moveRight);
break;
case(38):
moves.unshift(moveUp);
break;
case(37):
moves.unshift(moveLeft);
break;
}
});
Обратите внимание, что приведенный выше код отслеживает каждое движение, которое делает пользователь, поэтому, например, если вы быстро нажмете вниз, вверх, вниз, вверх, вниз, эта последовательность будет воспроизведена. В зависимости от вашего приложения вы можете добавить ограничения, чтобы, например, допускались только горизонтальные + диагональные перемещения и / или только перемещения, происходящие от нажатий клавиш, которые происходят в течение короткого периода времени.