Disable arrow key scrolling in users browser

后端 未结 3 1090
盖世英雄少女心
盖世英雄少女心 2020-11-29 20:46

I\'m making a game using canvas, and javascript.

When the page is longer than the screen (comments, etc.) pressing the down arrow scrolls the page down, and makes th

相关标签:
3条回答
  • 2020-11-29 21:20

    I've tried different ways of blocking scrolling when the arrow keys are pressed, both jQuery and native Javascript - they all work fine in Firefox, but don't work in recent versions of Chrome.
    Even the explicit {passive: false} property for window.addEventListener, which is recommended as the only working solution, for example here.

    In the end, after many tries, I found a way that works for me in both Firefox and 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
    });
    

    Quote for EventTarget.addEventListener() from MDN

    options Optional
       An options object specifies characteristics about the event listener. The available options are:

    capture
       A Boolean indicating that events of this type will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.
    once
       ...
    passive
       A Boolean that, if true, indicates that the function specified by listener will never call preventDefault(). If a passive listener does call preventDefault(), the user agent will do nothing other than generate a console warning. ...

    0 讨论(0)
  • 2020-11-29 21:32

    Summary

    Simply prevent the default browser action:

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

    Original answer

    I used the following function in my own game:

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

    The magic happens in e.preventDefault();. This will block the default action of the event, in this case moving the viewpoint of the browser.

    If you don't need the current button states you can simply drop keys and just discard the default action on the arrow keys:

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

    Note that this approach also enables you to remove the event handler later if you need to re-enable arrow key scrolling:

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

    References

    • MDN: window.addEventListener
    • MDN: window.removeEventListener
    0 讨论(0)
  • 2020-11-29 21:32

    For maintainability, I would attach the "blocking" handler on the element itself (in your case, the canvas).

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

    Why not simply do window.event.preventDefault()? MDN states:

    window.event is a proprietary Microsoft Internet Explorer property which is only available while a DOM event handler is being called. Its value is the Event object currently being handled.

    Further readings:

    • https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/view
    • https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
    0 讨论(0)
提交回复
热议问题