ChatGPT解决这个技术问题 Extra ChatGPT

在用户浏览器中禁用箭头键滚动

我正在使用画布和 javascript 制作游戏。

当页面长于屏幕(评论等)时,按下向下箭头会向下滚动页面,并使游戏无法进行。

当玩家只想向下移动时,我该怎么做才能防止窗口滚动?

我猜对于Java游戏,这样的,这不是问题,只要用户点击游戏。

我尝试了来自 How to disable page scrolling in FF with arrow keys 的解决方案,但我无法让它工作。


Z
Zeta

概括

只需 prevent the default 浏览器操作:

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

如果您需要支持 Internet Explorer 或其他旧版浏览器,请使用 e.keyCode 而不是 e.code,但请记住 keyCode is deprecated 并且您需要使用实际代码而不是字符串:

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

参考

MDN:window.addEventListener

MDN:window.removeEventListener

MDN:KeyboardEvent.code 接口


我真的很喜欢这个解决方案,但它似乎不适用于 chrome =/
@Kaninepete:出现语法错误,我在 keyup 侦听器中使用了 lC.keys 而不是 keys。修复了这个问题并在 Firefox 和 Chrome 中进行了测试。请注意,对 keys 的所有更改都是可选的,但由于您正在构建游戏...
如果您这样做,并且您的网页上有任何字段输入,那么您将无法使用空格键或箭头键来导航文本。我发现了很大的缺点。
请注意,您确实需要使用 keydown 而不是 keyup
这在 chrome 中仍然不起作用 :( RIP 我的蛇游戏
Y
Yom T.

为了可维护性,我将在元素本身(在您的情况下为画布)上附加“阻塞”处理程序。

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 事件处理程序时可用。它的值是当前正在处理的事件对象。

进一步阅读:

https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/view

https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key


我已经为此奋斗了好几个小时,你解决了它。谢谢!
a
almaceleste

我尝试了在按下箭头键时阻止滚动的不同方法,包括 jQuery 和本机 Javascript - 它们在 Firefox 中都可以正常工作,但在最新版本的 Chrome 中无法正常工作。
甚至是显式的 {passive: false} 属性对于 window.addEventListener,建议将其作为唯一可行的解决方案,例如 here

最后,经过多次尝试,我找到了一种适用于 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
});

MDNEventTarget.addEventListener() 的报价

options 可选 选项对象指定有关事件侦听器的特征。可用的选项有: capture 一个布尔值,指示这种类型的事件在被分派到 DOM 树中它下面的任何 EventTarget 之前将被分派到已注册的侦听器。一次 ... 被动 一个布尔值,如果为真,则表明侦听器指定的函数将永远不会调用 preventDefault()。如果被动侦听器确实调用了 preventDefault(),则用户代理只会生成控制台警告。 ...


J
JFS

这是为 React 重写的公认答案。

import { useEffect } from "react";

const usePreventKeyboardScrolling = () => {
  const onKeyDown = (e) => {
    if (
      ["Space", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"].indexOf(
        e.code
      ) > -1
    ) {
      e.preventDefault();
    }
  };

  useEffect(() => {
    window.addEventListener("keydown", onKeyDown, false);
    return () => window.removeEventListener("keydown", onKeyDown);
  });
};

export { usePreventKeyboardScrolling };