【问题标题】:How do I capture a keydown event on the canvas without interfering with the rest of my website?如何在画布上捕获 keydown 事件而不干扰我的网站的其余部分?
【发布时间】:2015-05-21 14:35:57
【问题描述】:

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

但是,当我使用 canvas.addEventListener() 和我使用它之前的相同参数时,我无法让画布关注事件。他们似乎根本没有注册。我曾尝试单击画布以使其“集中”,但这似乎没有任何作用。

所以问题是我怎样才能让画布只有画布才能监听 keydown 事件?

这可行,但会破坏我的表单

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

【问题讨论】:

  • 能否提供一个事件注册的示例代码?
  • 如果您需要更多信息,请告诉我?我想我处理了你的要求? keysDown 数组在我的主游戏循环中得到处理,并且在 case 32 上有更多代码来启动游戏。我在事件监听器函数中放了一个 console.log,当我有 canvas.add 而不是 add 时不会打印
  • 你在哪里声明keysDown[e.keyCode]数组?
  • 以上几行。只是一个空数组。在 keyup 上,我删除了该键码。这不是问题的一部分,因为该代码之前的 console.log 不会触发。

标签: javascript html canvas addeventlistener


【解决方案1】:

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

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>

【讨论】:

  • 我赞成这个,因为它可能会起作用,而且它是一个格式正确的答案,但胡安巴勃罗的回答首先打动了我,它对我有用,所以我接受了他的。
【解决方案2】:

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

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

希望它有效!

【讨论】:

    【解决方案3】:

    重要的部分是将画布的 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 旨在仅捕获可打印的键。所以选择适合您需求的任何东西。

    【讨论】:

    • 这似乎可行,但在触发任何键盘事件之前确实需要画布具有焦点。不是很意外,但我认为应该指出这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多