Отключить прокрутку клавиш со стрелками в браузере пользователей

Я делаю игру, используя холст и javascript.

Когда страница длиннее экрана (комментарии и т. Д.), Нажатие стрелки вниз прокручивает страницу вниз и делает игру невозможной.

Что я могу сделать, чтобы окно не прокручивалось, когда игрок просто хочет спуститься вниз?

Я полагаю, что с играми Java и т.п. это не проблема, пока пользователь нажимает на игру.

Я попробовал решение из: Как отключить прокрутку страницы в FF со стрелками, но я не мог заставить его работать.


person Kaninepete    schedule 18.01.2012    source источник


Ответы (3)


Резюме

Просто предотвратите действие браузера по умолчанию:

window.addEventListener("keydown", function(e) {
    if(["Space","ArrowUp","ArrowDown","ArrowLeft","ArrowRight"].indexOf(e.code) > -1) {
        e.preventDefault();
    }
}, false);

Если вам необходимо поддерживать Internet Explorer или другие старые браузеры, используйте e.keyCode вместо e.code, но помните, что _ 4_ устарело, и вам нужно использовать фактические коды вместо строк:

// Deprecated code!
window.addEventListener("keydown", function(e) {
    // space and arrow keys
    if([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
        e.preventDefault();
    }
}, false);

Оригинальный ответ

В своей игре я использовал следующую функцию:

var keys = {};
window.addEventListener("keydown",
    function(e){
        keys[e.code] = true;
        switch(e.code){
            case "ArrowUp": case "ArrowDown": case "ArrowLeft": case "ArrowRight":
            case "Space": e.preventDefault(); break;
            default: break; // do not block other keys
        }
    },
false);
window.addEventListener('keyup',
    function(e){
        keys[e.code] = false;
    },
false);

Волшебство происходит в e.preventDefault();. Это заблокирует действие по умолчанию для события, в данном случае перемещение точки обзора браузера.

Если вам не нужны текущие состояния кнопок, вы можете просто отбросить keys и просто отказаться от действия по умолчанию для клавиш со стрелками:

var arrow_keys_handler = function(e) {
    switch(e.code){
        case "ArrowUp": case "ArrowDown": case "ArrowLeft": case "ArrowRight": 
            case "Space": e.preventDefault(); break;
        default: break; // do not block other keys
    }
};
window.addEventListener("keydown", arrow_keys_handler, false);

Обратите внимание, что этот подход также позволяет удалить обработчик событий позже, если вам нужно повторно включить прокрутку клавиш со стрелками:

window.removeEventListener("keydown", arrow_keys_handler, false);

использованная литература

person Zeta    schedule 18.01.2012
comment
Мне очень нравится это решение, но оно не работает в chrome = / - person Kaninepete; 19.01.2012
comment
@Kaninepete: Произошла синтаксическая ошибка, я использовал lC.keys вместо keys в прослушивателе клавиш. Исправлено и протестировано в Firefox и Chrome. Обратите внимание, что все изменения в keys необязательны, но поскольку вы создаете игру ... - person Zeta; 19.01.2012
comment
в некоторых старых (мобильных) браузерах кажется, что клавиши со стрелками даже не запускают ключевые события ... :-( - person Michael; 26.09.2014
comment
Собственно, я пробовал несколько; Похоже, что действие WebKit по умолчанию - заставить клавиши со стрелками выполнять операции пользовательского интерфейса. - person Michael; 27.09.2014
comment
Если вы это сделаете, и у вас есть какие-либо поля для ввода на вашей веб-странице, вы не сможете использовать пробел или клавиши со стрелками для навигации по тексту. Большой недостаток я нашел. - person Single Entity; 15.04.2016
comment
@SingleEntity Ну, это явный недостаток. С другой стороны, вы редко получаете входные данные об играх, которые не обрабатываются самой игровой логикой. При этом вы можете просто отключить слушателя, пока фокус находится на интерактивном элементе, см. stackoverflow.com/questions/13570007/. - person Zeta; 15.04.2016
comment
Да, это именно то, что мне пришлось сделать - person Single Entity; 15.04.2016
comment
Обратите внимание, что вам действительно нужно использовать keydown, а не keyup. - person Ludder; 09.03.2018
comment
это все еще не работает в хроме :( RIP my snake game - person Mister SirCode; 02.12.2019
comment
Если вы пробуете это решение, но оно не работает. Убедитесь, что вы действительно используете keydown, а не другое ключевое событие, такое как keyup. - person Norman Breau; 05.12.2019
comment
Всем, кто пытается использовать keyCode developer.mozilla.org/en- US / docs / Web / API / KeyboardEvent / keyCode устарел. вместо этого используйте код developer.mozilla.org/en-US/docs / Web / API / KeyboardEvent / code - person A.D; 10.02.2021
comment
@ A.D Спасибо, исправлено. - person Zeta; 10.02.2021

Для удобства обслуживания я бы прикрепил обработчик «блокировки» к самому элементу (в вашем случае - холсту).

theCanvas.onkeydown = function (e) {
    if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
        e.view.event.preventDefault();
    }
}

Почему бы просто не сделать window.event.preventDefault()? В MDN говорится:

window.event - это проприетарное свойство Microsoft Internet Explorer, которое доступно только при вызове обработчика событий DOM. Его значение - это обрабатываемый в данный момент объект Event.

Дальнейшие чтения:

person Yom T.    schedule 11.01.2018

Я пробовал разные способы блокировки прокрутки при нажатии клавиш со стрелками, как jQuery, так и собственный Javascript - все они отлично работают в Firefox, но не работают в последних версиях Chrome.
Даже явное свойство {passive: false} для window.addEventListener, который рекомендуется как единственное рабочее решение, например здесь.

В конце концов, после многих попыток я нашел способ, который работает для меня как в Firefox, так и в Chrome:

window.addEventListener('keydown', (e) => {
    if (e.target.localName != 'input') {   // if you need to filter <input> elements
        switch (e.keyCode) {
            case 37: // left
            case 39: // right
                e.preventDefault();
                break;
            case 38: // up
            case 40: // down
                e.preventDefault();
                break;
            default:
                break;
        }
    }
}, {
    capture: true,   // this disables arrow key scrolling in modern Chrome
    passive: false   // this is optional, my code works without it
});

Цитата для EventTarget.addEventListener() из MDN

options Необязательно
Объект параметров указывает характеристики прослушивателя событий. Доступные варианты:

захват
Boolean, указывающий, что события этого типа будут отправлены зарегистрированному listener перед отправкой любому EventTarget под ним в дереве DOM.
один раз
...
пассивный
Boolean, который, если он истинен, указывает, что функция, указанная в listener, никогда не будет вызывать preventDefault(). Если пассивный прослушиватель действительно вызывает preventDefault(), пользовательский агент не будет делать ничего, кроме создания консольного предупреждения. ...

person almaceleste    schedule 01.11.2020