M4mkin_pr0ger
@M4mkin_pr0ger
Хачу пырфоманс

Как сделать плавное перемещение элемента по нажатию клавиш?

Обработчик нажатия клавиш таков:
document.onkeydown=function(event){
	switch(event.key){
		case 'ArrowUp':My-=1;M.style.top=(My+'vh');break;
		case 'ArrowRight':Mx+=1;M.style.left=(Mx+'vh');break;
		case 'ArrowDown':My+=1;M.style.top=(My+'vh');break;
		case 'ArrowLeft':Mx-=1;M.style.left=(Mx+'vh');break;};
};

"My" и "Mx" - положение элемента "M" (переменные)

Проблема: При зажатии клавиши, происходит однократное движение, далее задержка, и только потом постоянное движение элемента.

Цель: Избавиться от этой задержки

Думаю, моя проблема не уникальна и все уже ясно)

Если вы знаете более адекватный, рациональный, оптимальный вариант объявления подобного обработчика, то поделитесь мозгами, буду благодарен :)
  • Вопрос задан
  • 1016 просмотров
Решения вопроса 2
sergiks
@sergiks Куратор тега JavaScript
♬♬
Такое поведение происходит из-за того, что вы ловите событие нажатия, и из-за настроек компьютера.

Точно так же в любом текстовом поле, если нажать букву и держать, она сначала появится один раз, затем пауза, затем она станет добавляться с регулярной частотой.

Вместо этого используйте состояния. Когда клавишу нажали, игра перешла в состояние «едем вверх» например. И по таймеру или requestAnimationFrame() обновлять координаты игрока и дисплей.

Когда клавишу отпустили, игра перешла в состояние «всё, не едем».
Примерно так
var player = {x:200, y:200, el:document.getElementById('player')};
player.el.style.left = '' + Math.round(player.x) + 'px';
player.el.style.top  = '' + Math.round(player.y) + 'px';

var delta = {x:0, y:0};

document.addEventListener('keydown', function(e){
  if(     e.key == 'ArrowRight') delta.x = 1;
  else if(e.key == 'ArrowLeft')  delta.x = -1;
  else if(e.key == 'ArrowUp')    delta.y = -1;
  else if(e.key == 'ArrowDown')  delta.y = 1;
});

document.addEventListener('keyup', function(e){
  if(     e.key == 'ArrowRight') delta.x = 0;
  else if(e.key == 'ArrowLeft')  delta.x = 0;
  else if(e.key == 'ArrowUp')    delta.y = 0;
  else if(e.key == 'ArrowDown')  delta.y = 0;
});

var ts = null;
function step(timestamp) {
  if(!ts) ts = timestamp;
  var passed = timestamp - ts;
  //if(passed < 200) return window.requestAnimationFrame(step);
  ts = timestamp;
  if(delta.x || delta.y) {
    player.x += delta.x * passed / 10;
    player.y += delta.y * passed / 10;
    player.el.style.left = '' + Math.round(player.x) + 'px';
    player.el.style.top  = '' + Math.round(player.y) + 'px';
  };
  window.requestAnimationFrame(step);
}

window.requestAnimationFrame(step);


При таком подходе можно одновременно зажимать, скажем, стрелку влево и стрелку вверх – точка поедет по диагонали.
Фиддл.
Ответ написан
Комментировать
Stalker_RED
@Stalker_RED
Метод №1:
Поменять вот эти настройки:
0iziOT.png

Метод №2:
После первого keydown включать непрерывное движение и продолжать пока не сработает keyup
bJ7iPh.png

Вот вам тестовый стенд

И да, вам еще предстоит помучаться с кроссбраузерностью.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы