Fiddle: http://jsfiddle.net/ATUEx/
Create a temporary cache to remember your key strokes.
An implementation of handling two keys would follow this pattern:
<keydown>
- Clear previous time-out.
- Check whether the a key code has been cached or not.
If yes, and valid combination:
-
Delete all cached key codes
-
Execute function for this combination
else
-
Delete all cached key codes
-
Store the new key code
-
Set a time out to clear the keycodes (see below), with a reasonable delay
- Repeat 1
A reasonable delay: Experiment to know which timeout is sufficient for you. When the delay is too short, the next initiated event will not find a previously entered key code.
When the delay is too long, the key strokes will stack when you don't want it.
Code
I have created an efficient function, keeping your code in mind. You should be able to implement it very easily.
(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;
})();
At the end of the anonymous function, the keydown
event listener is added. This event is fired only once (when the key is pressed down). When a second key is pressed fast enough, the code recognises two key strokes after each other, and calls keyCombi()
.
I have designed keyCombi
to be intelligent, and only call animation.move(x,y)
when the values are changed. Also, I've implemented the possiblity to deal with two directions at a time.
Note: I have contained the functions within an anonymous function wrapper, so that the variables are not defined in the global (window
) scope. If you don't care about scoping, feel free to remove the first and last line.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…