文档.Onkeydown冲突在两个不同的画布上



我试图设置两个不同的画布包含自己的实体,不同的键盘输入可移动。每个画布都有自己的脚本文件。然而,只有第二个画布似乎是活动的,通过测试,我得出的结论是,第二个画布的document.onkeydown()函数使我的第一个画布"非活动"。(绘制功能是好的,但文件。onkeydown和onkeyup不工作),但我不知道为什么。

下面是第一个画布的代码:
var canvas;
var player_y = 480/2;
const paddle_height = 100;
const paddle_width = 20;
document.addEventListener('DOMContentLoaded', function () {
canvas = document.getElementById('canvas');
draw();
});
function draw() {
var context = canvas.getContext('2d');
//canvas
context.fillStyle = color[3];
context.fillRect(0, 0, canvas.width, canvas.height);
// Draw middle line
context.strokeStyle = color[1];
context.beginPath();
context.moveTo(canvas.width / 2, 0);
context.lineTo(canvas.width / 2, canvas.height);
context.stroke();
//draw left paddle
context.fillStyle = color[1];
context.beginPath();
context.fillRect(10, player_y-paddle_height/2, paddle_width, paddle_height);
context.fill();
}
var UP = false; 
var DOWN = false;
function move() {
if(UP && player_y > paddle_height/2 ) { 
player_y -= 5;
}
if(DOWN && player_y < 480 - paddle_height/2) {
player_y += 5;  
}   
draw(); 
}
document.onkeydown = function(e) {
if(e.keyCode == 38) UP = true;
if(e.keyCode == 40) DOWN = true;
}
document.onkeyup = function(e) {
if(e.keyCode == 38) UP = false;
if (e.keyCode == 40) DOWN = false;
}
setInterval (update, 10);
function update() {
move();
}

下面是第二个画布的代码:

var canvas_exemple;
var cube = {
sz: 50,
x: 400/2,
y: 200/2,
sp: 5
}

document.addEventListener('DOMContentLoaded', function () {
canvas_exemple = document.getElementById('canvas_exemple');
draw_exemple();
});

function draw_exemple() {
var context = canvas_exemple.getContext('2d');
//canvas
context.fillStyle = "#242423";
context.fillRect(0, 0, canvas_exemple.width, canvas_exemple.height);

//draw cube
context.fillStyle = "#c70e0e";
context.beginPath();
context.fillRect(cube.x, cube.y, cube.sz, cube.sz);
context.fill();
}
function move_exemple() {
document.onkeydown = function (e) {
if (e.keyCode == 90 && cube.y > 0) cube.y -= cube.sp;
if (e.keyCode == 83 && cube.y < 200 - cube.sz) cube.y += cube.sp;
if (e.keyCode == 81 && cube.x > 0) cube.x -= cube.sp;
if (e.keyCode == 68 && cube.x < 400 - cube.sz) cube.x += cube.sp;
draw_exemple();
}
}

…但我不知道为什么

因为你覆盖了它:

// First file:
document.onkeydown = function (e) { /*...*/ };
// Second file:
document.onkeydown = function (e) { /*...*/ }; // <=== Overwrites the first

这是对属性的赋值。一个属性只能有一个值(尽管DOM中有一些奇怪的属性,比如document.cookie)。

如果你想在document上有多个keydown处理程序,使用addEventListener,而不是赋值,但你可能不希望这样。如果将keydown的两个事件处理程序放在同一个文档上,会接到电话。你如何决定谁应该做某事?

相反,将处理程序放在canvas元素上,而不是document。这确实意味着用户必须聚焦画布才能让键盘事件到达它,但是您有两个画布,因此您需要某种方式让用户指示他们将输入定向到哪个画布。(注意,为了使canvas元素更容易聚焦,你可能想把tabindex="0"放在它上面[详细信息在这里]。)

(如果您愿意,您仍然可以在document上使用处理程序,但要查看事件是否通过相关的canvas传播,但在这种情况下,将处理程序添加到canvas更简单。)

我在下面包含了一个例子。在这个例子中,有很多重复的代码,通常我会创建一个函数,我可以把东西传递进去,但是我把它们分开了,因为在你的问题中,代码是分开的有时重复的代码比参数化的代码更容易读。您可以使用鼠标或tab键在画布之间切换。活动画布周围有一个绿色边框。

// Canvas 1
const canvas1 = document.getElementById("canvas1");
const ctx1 = canvas1.getContext("2d");
let x1 = Math.floor(canvas1.width / 2);
let y1 = Math.floor(canvas1.height / 2);
draw1();
canvas1.addEventListener("keydown", (event) => {
switch (event.key) {
case "ArrowLeft":
x1 = x1 > 0 ? x1 - 1 : x1;
break;
case "ArrowRight":
x1 = x1 < 300 ? x1 + 1 : x1;
break;
case "ArrowUp":
y1 = y1 > 0 ? y1 - 1 : y1;
break;
case "ArrowDown":
y1 = y1 < 300 ? y1 + 1 : y1;
break;
default:
return;
}
event.preventDefault();
draw1();
});
function draw1() {
ctx1.fillRect(x1, y1, 1, 1);
}
// Canvas 2
const canvas2 = document.getElementById("canvas2");
const ctx2 = canvas2.getContext("2d");
let x2 = Math.floor(canvas2.width / 2);
let y2 = Math.floor(canvas2.height / 2);
ctx2.fillRect(x2, y2, 1, 1);
canvas2.addEventListener("keydown", (event) => {
let originalX = x2;
let originalY = y2;
switch (event.key) {
case "ArrowLeft":
x2 = x2 > 0 ? x2 - 5 : x2;
break;
case "ArrowRight":
x2 = x2 < 300 ? x2 + 5 : x2;
break;
case "ArrowUp":
y2 = y2 > 0 ? y2 - 5 : y2;
break;
case "ArrowDown":
y2 = y2 < 300 ? y2 + 5 : y2;
break;
default:
return;
}
event.preventDefault();
if (x2 !== originalX || y2 !== originalY) {
ctx2.strokeStyle = "blue";
ctx2.beginPath();
ctx2.moveTo(originalX, originalY);
ctx2.lineTo(x2, y2);
ctx2.closePath();
ctx2.stroke();
}
});
// Focus the first canvas by default
canvas1.focus();
html {
box-sizing: border-box;
font-family: sans-serif;
}
*, *:before, *:after {
box-sizing: inherit;
}
canvas {
border: 1px solid grey;
margin: 8px;
}
canvas:focus {
outline: green solid 3px;
}
<div>Canvas 1:</div>
<canvas id="canvas1" tabindex="0" width="200" height="200"></canvas>
<div>Canvas 2:</div>
<canvas id="canvas2" tabindex="0" width="200" height="200"></canvas>

最新更新