如何在不干扰网站其余部分的情况下捕获 canvas 上的按键事件?

How do I capture a keydown event on the canvas without interfering with the rest of my website?

我正在开发一个 canvas 游戏,使用一些教程并调整它们以实现一些 AI 交互。游戏运行良好,除了我的事件侦听器此时刚刚添加到文档中。当我将游戏移至我的实际网站时,这成为了一个问题,因为我需要 e.preventDefault 来防止页面滚动。没什么大不了的,直到人们想输入我的联系表并且他们无法使用 space 栏或箭头键。足够简单的修复似乎只是将事件侦听器添加到我的 canvas.

但是,当我使用 canvas.addEventListener() 时使用的参数与之前使用的相同,我无法让 canvas 关注事件。他们似乎根本没有注册。我试过点击 canvas 来获取它 "focussed" 但这似乎没有任何作用。

所以问题是如何让 canvas 并且只有 canvas 监听按键事件?

这有效但破坏了我的表格

addEventListener('keydown', function(e) {
    keysDown[e.keyCode] = true;
    switch(e.keyCode) {
        case 37: case 38: case 39: case 40:
        case 32: e.preventDefault(); break;
        default: break;
    }
}, false);

这行不通

var canvas = document.getElementById('world');
canvas.addEventListener('keydown', function(e) {
    keysDown[e.keyCode] = true;
    switch(e.keyCode) {
        case 37: case 38: case 39: case 40:
        case 32: e.preventDefault(); break;
        default: break;
    }
}, false);

我处理它的方式 in my game engine 是我将 canvas 放在 div 中,然后从那里捕获事件。确保在 div 上设置 tabindex 以便它可以聚焦。

var ctx = document.querySelector('canvas').getContext('2d');
ctx.rect(0, 0, 320, 240);
ctx.fillStyle = '#0F0';
ctx.fill();
var container = document.querySelector('div');
container.addEventListener('keypress', function(e) {
  console.log(e);
});
div:focus {
  outline: none;
}
<div tabindex="1">
  <canvas width="320" height="240"></canvas>
</div>

你应该检查另一个问题: addEventListener for keydown on Canvas

解决方法是缓存最后一个获得焦点的元素,然后询问它是否是 canvas,然后做一些不同的事情。

希望有用!

重要的部分是将 canvas 的 tabIndex 设置为 1(这是使任何元素都可聚焦的肮脏技巧)。

const canvasDiv = document.getElementById('my_canvas')
canvasDiv.childNodes[0].tabIndex = '1'

现在您可以:

canvasDiv.addEventListener('keyup', (e) => {
    console.log(e,keyCode)
}, false)

请注意,我使用 keyup - 因为它还捕获 Del、Home、End、Ins... 按钮,keydown 捕获只有那些的Ins。 keypress 旨在仅捕获可打印的键。所以选择适合您的需求。