Desativar a rolagem da tecla de seta no navegador do usuário

87

Estou fazendo um jogo usando canvas e javascript.

Quando a página é mais longa que a tela (comentários, etc.), pressionar a seta para baixo rola a página para baixo e torna o jogo impossível de jogar.

O que posso fazer para evitar que a janela role quando o jogador deseja apenas se mover para baixo?

Acho que com jogos Java, e tal, isso não é um problema, desde que o usuário clique no jogo.

Tentei a solução em: Como desativar a rolagem de página no FF com as teclas de seta , mas não consegui fazer funcionar.

Kaninepete
fonte

Respostas:

164

Resumo

Simplesmente evite a ação padrão do navegador:

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

Resposta original

Usei a seguinte função no meu próprio jogo:

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);

A mágica acontece em e.preventDefault();. Isso bloqueará a ação padrão do evento, neste caso movendo o ponto de vista do navegador.

Se você não precisa dos estados atuais do botão, pode simplesmente soltar keyse simplesmente descartar a ação padrão nas teclas de seta:

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);

Observe que essa abordagem também permite que você remova o manipulador de eventos posteriormente, se for necessário reativar a rolagem da tecla de seta:

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

Referências

Zeta
fonte
8
Gosto muito desta solução, mas parece que não funciona em chrome = /
Kaninepete
1
@Kaninepete: Ocorreu um erro de sintaxe, usei em lC.keysvez de keysno ouvinte keyup. Corrigido isso e testado no Firefox e Chrome. Observe que todas as alterações em keyssão opcionais, mas como você está criando um jogo ...
Zeta
em alguns navegadores mais antigos (móveis), parece que as teclas de seta nem mesmo disparam eventos importantes ... :-(
Michael
1
Se você fizer isso e tiver entradas de campo em sua página da web, não será possível usar a barra de espaço ou as teclas de seta para navegar no texto. Grande desvantagem que encontrei.
Entidade Única de
9
Observe que você realmente precisa usar keydowne não keyup.
Ludder,
4

Para facilidade de manutenção, eu anexaria o manipulador de "bloqueio" ao próprio elemento (no seu caso, a tela).

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

Por que não simplesmente fazer window.event.preventDefault()? Estados MDN :

window.eventé uma propriedade proprietária do Microsoft Internet Explorer que está disponível apenas enquanto um manipulador de eventos DOM está sendo chamado. Seu valor é o objeto Event que está sendo manipulado.

Leituras adicionais:

Yom S.
fonte
0

Eu tentei diferentes maneiras de bloquear a rolagem quando as teclas de seta são pressionadas, tanto jQuery quanto Javascript nativo - todos funcionam bem no Firefox, mas não funcionam nas versões recentes do Chrome.
Mesmo a {passive: false}propriedade explícita para window.addEventListener, que é recomendada como a única solução de trabalho, por exemplo aqui .

No final, depois de muitas tentativas, descobri uma maneira que funciona para mim tanto no Firefox quanto no 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
});

Cotação para EventTarget.addEventListener()de MDN

options Opcional
   Um objeto de opções especifica características sobre o ouvinte de evento. As opções disponíveis são:

capture
   A Booleanindicando que eventos desse tipo serão despachados para o registrado listenerantes de serem despachados para qualquer um EventTargetabaixo dele na árvore DOM.
uma vez
   ...
passivo
   A Booleanque, se verdadeiro, indica que a função especificada por listenernunca será chamada preventDefault(). Se um ouvinte passivo chamar preventDefault(), o agente do usuário não fará nada além de gerar um aviso de console. ...

almaceleste
fonte