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.

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


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:


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. ...

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.