Отключите клавиши со стрелками от прокрутки, только когда пользователь взаимодействует с ‹canvas›

Я добавил прослушиватель событий в JS для прослушивания событий keyup / keydown, я пытаюсь переместить спрайт по холсту HTML. У меня это в основном работает, но страница прокручивается, когда пользователь нажимает клавиши со стрелками.

Я возвращаю false, и это, похоже, не работает. Кроме того, я понимаю, что возврат false таким образом отключит прокрутку кнопки со стрелкой для всей страницы. Я хотел бы отключить это только тогда, когда пользователь взаимодействует с самим холстом.

Вот мой слушатель событий:

addEventListener('keydown', function(e){
    move = false;
    x = false;
    y = false;
    var keycode;
    if (window.event) keycode = window.event.keyCode;
    else if (e) keycode = e.which;
    switch(keycode){
        case 37:
            move = true;
            x = 'negative';
        break;
        case 38:
            move = true;
            y = 'negative'
        break;
        case 39:
            move = true;
            x = 'positive'
        break;
        case 40:
            move = true;
            y = 'positive'
        break;
    }
    if(move){
        animation.move(x,y);
    }
    return false;
})

Изменить:

Приведенный ниже ответ дает хорошее представление о том, как убедиться, что холст сфокусирован, но я все еще озадачен, почему возвращение false в моей функции EventListener, которая возвращает false, не отключает прокрутку.


person Chris Sobolewski    schedule 29.09.2011    source источник


Ответы (3)


Пока вы каким-то образом фокусируете свой холст (например, canvas.tabIndex = 1;), вы можете просто добавить e.preventDefault() прямо перед вашим return false, и он будет работать.

Пример:

http://jsfiddle.net/faAkN/

person Simon Sarris    schedule 29.09.2011
comment
Спасибо. Сработало у меня! - person ncmathsadist; 24.01.2017

У меня была аналогичная проблема, и я решил ее исправить.

Вот что я придумал:

function $(){
  return document.querySelector.apply(document,arguments);
}
var canvas = $('canvas'),
    keysDown = []; // You can also define this as an object, {}
canvas.tabIndex = 0;
canvas.onclick = function(e){
  document.body.scrollTop = canvas.offsetTop; // scrolls to canvas element
  canvas.focus(); // re-focuses canvas in case the scroll unfocused it
}
canvas.onkeydown = canvas.onkeyup = function(e){
  keysDown[e.keyCode] = e.type == 'keydown';
  e.preventDefault();
  return false;
}
function isDown(key){
  return keysDown[key];
}
function resetMap(){
  keysDown = [];
  return false;
}

Чтобы проверить, не нажата ли клавиша, используйте isDown(keycode) либо в цикле интервалов, либо в функции нажатия клавиши.

Для обычного ключевого слушателя:

canvas.onkeydown = canvas.onkeyup = function(e){
  // [...]
  if(isDown(17) && isDown(32)){ // Ctrl + Space
    alert('Ctrl and Space were pressed');
    resetMap();
  }
  e.preventDefault();
  return false;
}

Для быстрого прослушивания клавиш, аналогичного Key.isDown в ActionScript 2.0.

function KeyLoop(){
  if(isDown(17) && isDown(32)){ // Ctrl + Space
    console.log('Lots of text');
    resetMap();
  }
  setTimeout(keyLoop,1000/24); // @ 24 fps
}
keyLoop();

Я предлагаю другое действие по двум причинам: 1) смешивание alert() с повторяющимся интервалом никогда не является хорошей идеей и 2) чтобы продемонстрировать отсутствие задержки, что делает эту функцию похожей на функцию AS2 Key.isDown(). Чтобы увидеть записанный текст, запустите firebug или обычную консоль JavaScript. В Chrome это Ctrl Shift J. В Firefox Ctrl Shift K.


Это должно решить вашу проблему с прокруткой, сосредоточив внимание на элементе при щелчке по холсту. Дополнительным преимуществом является то, что вы можете проверять наличие нескольких ключей одновременно, поскольку вы используете keysDown[] как абстракцию от исходного события, что упрощает создание 8-направленной игры.

person Braden Best    schedule 15.12.2012
comment
После дальнейшего тестирования я понял, что это не прокрутка до диапазона. Фактически он прокручивается до элемента <input>, который я использовал изначально. Лучше всего писать для ориентации document.body.scrollTop=canvas.offsetTop в функции canvas.onclick. Хотя canvas.focus() автоматически ориентируется по холсту, вы заметите, что он оставляет пространство вверху или внизу. - person Braden Best; 15.12.2012

Вы пробовали что-то подобное?

<script type="text/javascript">
    canvas_active = false;
</script>

<canvas onfocus="javascript: canvas_active = true;" onblur="javascript: canvas_active = false;" />

Затем в вашем текущем методе проверьте, истинно ли canvas_active, и если да, верните false, иначе верните true. Это сработает только в том случае, если холст будет сфокусирован все время, пока они его перемещают.

person Furbeenator    schedule 29.09.2011
comment
Это неплохая идея, хотя я бы предпочел не использовать встроенный javascript для разделения проблем. - person Chris Sobolewski; 30.09.2011
comment
Элемент холста нельзя сфокусировать. Вы можете использовать tabindex=0, чтобы сделать его фокусируемым. - person pimvdb; 30.09.2011
comment
Хороший, pimvdb. Кроме того, Крис, вы можете использовать jQuery для привязки методов onfocus и onblur: $('#canvas_name').focus(function() { canvas_active = true; }); $('#canvas_name').blur(function() { canvas_active = false; }); - person Furbeenator; 30.09.2011