我试图让用户使用箭头键移动页面上的元素。到目前为止,我的运动是上/下/左/右,但不是对角线(同时按下两个箭头键)。
我的听众看起来像这样:
addEventListener('keydown', function(e){
move = false;
x = false;
y = false;
var keycode;
if (window.event) keycode = window.event.keyCode;
else if (e) keycode = e.which;
switch(keycode){
case 37:
move = true;
x = 'negative';
//prevent page scroll
e.preventDefault()
break;
case 38:
move = true;
y = 'negative'
//prevent page scroll
e.preventDefault()
break;
case 39:
move = true;
x = 'positive'
//prevent page scroll
e.preventDefault()
break;
case 40:
move = true;
y = 'positive'
//prevent page scroll
e.preventDefault()
break;
}
if(move){
animation.move(x,y);
}
return false;
})
这个想法是,如果用户按下箭头键,它会将x
和y
设置为negative
或positive
,并触发move()函数,它将在预期的方向上移动元素预设数量的像素,如果按下两个键,则会触发第二个事件...我也希望能够通过释放和按键让用户无可奈何地改变方向然而,如果用户按下另一个方向键,他们似乎需要等待一个动作才能发生,除非他们完全释放键然后按另一个键,它将不会响应第二个密钥,直到第一个密钥被释放。
答案 0 :(得分:9)
小提琴:http://jsfiddle.net/ATUEx/
创建一个临时缓存以记住您的击键。
处理两个密钥的实现将遵循以下模式:
<keydown>
-
删除所有缓存的密钥代码-
执行此组合的功能-
删除所有缓存的密钥代码-
存储新的密钥代码-
设置超时以清除密钥代码(见下文),并有合理的延迟合理的延迟:尝试知道哪个超时足够您。当延迟太短时,下一个启动的事件将找不到先前输入的密钥代码。
当延迟太长时,如果你不想要它,键击将叠加。
<小时/>
我创建了一个高效的功能,牢记您的代码。你应该能够很容易地实现它。
(function(){ //Anonymous function, no leaks
/* Change the next variable if necessary */
var timeout = 200; /* Timeout in milliseconds*/
var lastKeyCode = -1;
var timer = null;
function keyCheck(ev){
var keyCode = typeof ev.which != "undefined" ? ev.which : event.keyCode;
/* An alternative way to check keyCodes:
* if(keyCode >= 37 && keyCode <= 40) ..*/
/*37=Left 38=Up 39=Right 40=Down */
if([37, 38, 39, 40].indexOf(keyCode) != -1){
/* lastKeyCode == -1 = no saved key
Difference betwene keyCodes == opposite keys = no possible combi*/
if(lastKeyCode == -1 || Math.abs(lastKeyCode - keyCode) == 2){
refresh();
lastKeyCode = keyCode;
} else if(lastKeyCode == keyCode){
clear([lastKeyCode]);
} else {
/* lastKeyCode != -1 && keyCode != lastKeyCode
and no opposite key = possible combi*/
clear([lastKeyCode, keyCode]);
lastKeyCode = -1
}
ev.preventDefault(); //Stop default behaviour
ev.stopPropagation(); //Other event listeners won't get the event
}
/* Functions used above, grouped together for code readability */
function reset(){
keyCombi([lastKeyCode]);
lastKeyCode = -1;
}
function clear(array_keys){
clearTimeout(timer);
keyCombi(array_keys);
}
function refresh(){
clearTimeout(timer);
timer = setTimeout(reset, timeout);
}
}
var lastX = false;
var lastY = false;
function keyCombi(/*Array*/ keys){
/* Are the following keyCodes in array "keys"?*/
var left = keys.indexOf(37) != -1;
var up = keys.indexOf(38) != -1;
var right = keys.indexOf(39) != -1;
var down = keys.indexOf(40) != -1;
/* What direction? */
var x = left ? "negative" : right ? "positive" : false;
var y = up ? "negative" : down ? "positive" : false;
/* Are we heading to a different direction?*/
if(lastX != x || lastY != y) animation.move(x, y);
lastX = x;
lastY = y;
}
//Add event listener
var eventType = "keydown";window["on"+eventType] = keyCheck;
})();
在匿名函数结束时,添加了keydown
事件侦听器。此事件仅触发一次(按下该键时)。当按下第二个键足够快时,代码会识别出彼此之后的两个击键,并调用keyCombi()
。
我设计keyCombi
是智能的,只有在值发生变化时才调用animation.move(x,y)
。另外,我已经实现了一次处理两个方向的可能性。
注意:我在匿名函数包装器中包含了这些函数,因此未在全局(window
)范围内定义变量。如果您不关心范围界定,请随意删除第一行和最后一行。
答案 1 :(得分:2)
以下是您的代码,稍作修改...... http://jsfiddle.net/w8uNz/它只是工作。在父元素上移动元素。
Rob W是对的,您应该在一段时间内按下动态的密钥缓存。但为了什么?如果你正在制作一个动态游戏 - 必须有更高的抽象。总的来说,如果你想做那样的事情,你需要提高你的编码水平。 (或者它只会给你带来麻烦。)
答案 2 :(得分:1)
从逻辑上讲,这听起来很简单: