Wyłącz przewijanie za pomocą klawiszy strzałek w przeglądarce użytkowników

87

Tworzę grę, używając płótna i javascript.

Gdy strona jest dłuższa niż ekran (komentarze itp.), Naciśnięcie strzałki w dół przewija stronę w dół i uniemożliwia rozpoczęcie gry.

Co mogę zrobić, aby zapobiec przewijaniu się okna, gdy gracz chce tylko zejść w dół?

Myślę, że z grami Java i takimi nie stanowi to problemu, o ile użytkownik kliknie grę.

Wypróbowałem rozwiązanie z: Jak wyłączyć przewijanie strony w FF za pomocą klawiszy strzałek , ale nie mogłem go uruchomić.

Kaninepete
źródło

Odpowiedzi:

165

Podsumowanie

Po prostu wyłącz domyślne działanie przeglądarki:

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

Oryginalna odpowiedź

W mojej własnej grze użyłem następującej funkcji:

var keys = {};
window.addEventListener("keydown",
    function(e){
        keys[e.keyCode] = true;
        switch(e.keyCode){
            case 37: case 39: case 38:  case 40: // Arrow keys
            case 32: e.preventDefault(); break; // Space
            default: break; // do not block other keys
        }
    },
false);
window.addEventListener('keyup',
    function(e){
        keys[e.keyCode] = false;
    },
false);

Magia dzieje się w e.preventDefault();. Spowoduje to zablokowanie domyślnej akcji zdarzenia, w tym przypadku przesunięcia punktu widzenia przeglądarki.

Jeśli nie potrzebujesz aktualnych stanów przycisków, możesz po prostu upuścić keysi po prostu odrzucić domyślną akcję na klawiszach strzałek:

var arrow_keys_handler = function(e) {
    switch(e.keyCode){
        case 37: case 39: case 38:  case 40: // Arrow keys
        case 32: e.preventDefault(); break; // Space
        default: break; // do not block other keys
    }
};
window.addEventListener("keydown", arrow_keys_handler, false);

Zwróć uwagę, że to podejście umożliwia również późniejsze usunięcie programu obsługi zdarzeń, jeśli musisz ponownie włączyć przewijanie za pomocą klawiszy strzałek:

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

Bibliografia

Zeta
źródło
8
Naprawdę podoba mi się to rozwiązanie, ale wygląda na to, że nie działa w chrome = /
Kaninepete
1
@Kaninepete: Wystąpił błąd składni, użyłem lC.keyszamiast keysnasłuchiwania klucza. Naprawiono to i przetestowałem w Firefoksie i Chrome. Zauważ, że wszystkie zmiany keyssą opcjonalne, ale ponieważ tworzysz grę ...
Zeta
w niektórych starszych (mobilnych) przeglądarkach wydaje się, że klawisze strzałek nawet nie uruchamiają kluczowych zdarzeń ... :-(
Michael
1
Jeśli to zrobisz i masz jakieś pola wejściowe na swojej stronie internetowej, nie będziesz w stanie używać spacji lub klawiszy strzałek do poruszania się po tekście. Znalazłem dużą wadę.
Single Entity
9
Zauważ, że naprawdę musisz użyć, keydowna nie keyup.
Ludder
4

Aby zachować łatwość obsługi, założyłbym obsługę "blokującą" na samym elemencie (w twoim przypadku na płótnie).

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

Dlaczego po prostu nie zrobić window.event.preventDefault()? MDN stwierdza:

window.eventto zastrzeżona właściwość przeglądarki Microsoft Internet Explorer, która jest dostępna tylko wtedy, gdy wywoływana jest procedura obsługi zdarzeń DOM. Jego wartością jest aktualnie obsługiwany obiekt Event.

Dalsze lektury:

Yom S.
źródło
1

Próbowałem różnych sposobów blokowania przewijania po naciśnięciu klawiszy strzałek, zarówno jQuery, jak i natywny JavaScript - wszystkie działają dobrze w Firefoksie, ale nie działają w najnowszych wersjach Chrome.
Nawet jawna {passive: false}właściwość for window.addEventListener, która jest zalecana jako jedyne działające rozwiązanie, na przykład tutaj .

W końcu po wielu próbach znalazłem sposób, który działa dla mnie zarówno w Firefoksie, jak i 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
});

Wycena EventTarget.addEventListener()z MDN

opcje Opcjonalne
   Obiekt opcji określa charakterystykę detektora zdarzeń. Dostępne opcje to:

przechwytywanie
   A Booleanwskazujące, że zdarzenia tego typu będą wysyłane do zarejestrowanego listenerprzed wysłaniem do dowolnego znajdującego się EventTargetpod nim w drzewie DOM.
raz
   ...
pasywne
   A, Booleanktóre, jeśli jest prawdziwe, wskazuje, że funkcja określona przez listenernigdy nie zostanie wywołana preventDefault(). Jeśli pasywny nasłuchujący zadzwoni preventDefault(), agent użytkownika nie zrobi nic poza wygenerowaniem ostrzeżenia konsoli. ...

almaceleste
źródło