javascript同时触发多个keydown事件使浮动元素移动

之前在写坦克大战时就遇到一个问题,在移动坦克的同时还要发射炮弹。这个时候如果使用onkeydow事件的话,就会在发射炮弹时停止移动,没法同时触发两个keydown事件,为了解决这个问题,我通过在声明多个对象来记录按键的状态。

以移动为例子,假如要通过方向来移动某个在浏览器上的元素,首先给这个元素浮动(在使用canvas画布之类的可以使用里面的API改变元素的位置,这里通过将元素浮动来举例子)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<head>
<meta charset="UTF-8">
<title>move</title>
<style>
#move {
position: fixed;
top: 0px;
left: 0px;
}
</style>
</head>

<body>
<div id="move">移动元素</div>
</body>

这样元素的html和css就写好了,接下来来写js部分,为了得到各个方向按键对应的键码,我们用下面的代码在控制台打印出对应的键码。

1
2
3
4
window.οnkeydοwn=function(event){
console.log(event.keyCode);
}
//上:38 下:40 左:37 右:39

然后用下面的代码移动元素,当按下对应按键的时候,元素每次移动1px。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var move = document.getElementById('move');
window.onkeydown = function(event) {
if (event.keyCode == 38) { //上
move.style.top = parseInt(window.getComputedStyle(move, null).top) - 1 + "px";
}
if (event.keyCode == 40) { //下
move.style.top = parseInt(window.getComputedStyle(move, null).top) + 1 + "px";
}
if (event.keyCode == 37) { //左
move.style.left = parseInt(window.getComputedStyle(move, null).left) - 1 + "px";
}
if (event.keyCode == 39) { //右
move.style.left = parseInt(window.getComputedStyle(move, null).left) + 1 + "px";
}
}

但是这个时候我们就会发现,没法同时触发两个方向,即没法斜向移动,而且在改变方向时还会有明显的停顿,为了解决这个问题,我写了个对象来储存按键的状态。

1
2
3
4
5
6
var codeType = {
"up": false,
"down": false,
"left": false,
"right": false
}

我的思路是这样的,为每个方向设置状态,初始为false,通过keydown事件将其变为true,当状态为true时,执行对应方向的移动,同时要通过keyup事件使其变回false,否则其会不停地移动。将移动地方法放在一个计时器里,就能实现元素的斜向移动了。完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#move {
position: fixed;
top: 0px;
left: 0px;
}
</style>
</head>

<body>
<div id="move">移动元素</div>
</body>
<script>
var move = document.getElementById('move');
var codeType = {
"up": false,
"down": false,
"left": false,
"right": false
}
setInterval(Move, 40);
window.onkeydown = function(event) {
if (event.keyCode == 38) { //上
codeType.up = true;
}
if (event.keyCode == 40) { //下
codeType.down = true;
}
if (event.keyCode == 37) { //左
codeType.left = true;
}
if (event.keyCode == 39) { //右
codeType.right = true;
}
}
window.onkeyup = function(event) {
if (event.keyCode == 38) { //上
codeType.up = false;
}
if (event.keyCode == 40) { //下
codeType.down = false;
}
if (event.keyCode == 37) { //左
codeType.left = false;
}
if (event.keyCode == 39) { //右
codeType.right = false;
}
}

function Move() {
if (codeType.up) { //上
move.style.top = parseInt(window.getComputedStyle(move, null).top) - 1 + "px";
}
if (codeType.down) { //下
move.style.top = parseInt(window.getComputedStyle(move, null).top) + 1 + "px";
}
if (codeType.left) { //左
move.style.left = parseInt(window.getComputedStyle(move, null).left) - 1 + "px";
}
if (codeType.right) { //右
move.style.left = parseInt(window.getComputedStyle(move, null).left) + 1 + "px";
}
}
</script>

</html>