キーボードの応答は、驚くほど複雑になる可能性があります。通常、発生するすべてのキーダウンイベントに注意を払う必要はありません。これは、ユーザーのキーボードと設定に依存するためです。たとえば、1つのイベントが最初に発生し、一時停止した後、高速ストリームが発生します。また、ユーザーが2つのキーを同時に押した場合の対処方法の問題もあります。
次のコードは、個別の更新機能を使用して、キーボードの応答をアニメーションから分離します。新しい矢印キーを押すと、正方形は最初に1ステップ(5pxに設定)移動し、100ms後にキーが離されるまで継続的に移動します。
(フィドル)
var directions = [],
lastPressTime, stepped, ti, frameRate = 30,
squareSpeed = 5, stepTime = 100;
function update() {
var x, y, d = directions[directions.length - 1],
square = document.getElementById('square');
if (!d) {
return;
}
if (new Date().getTime() < lastPressTime + stepTime) {
if (stepped) { // already stepped and <100ms has passed
return; // so do nothing
}
else {
stepped = true;
}
}
x = square.offsetLeft;
y = square.offsetTop;
if (d == 'left') {
x -= squareSpeed;
}
else if (d == 'right') {
x += squareSpeed;
}
else if (d == 'up') {
y -= squareSpeed;
}
else if (d == 'down') {
y += squareSpeed;
}
square.style.left = x + 'px';
square.style.top = y + 'px';
}
function checkArrowKeys(e) {
var arrs = [],
key = window.event ? event.keyCode : e.keyCode;
arrs[37] = 'left';
arrs[38] = 'up';
arrs[39] = 'right';
arrs[40] = 'down';
if (arrs[key]) {
return arrs[key];
}
}
document.onkeydown = function(e) {
var d = checkArrowKeys(e);
if (d) {
// Key not already pressed; add it to array
// of directions and step forward
if (directions.indexOf(d) === -1) {
directions.push(d);
lastPressTime = new Date().getTime();
stepped = false;
}
if (!ti) {
ti = setInterval(update, 1000 / frameRate);
}
}
};
document.onkeyup = function(e) {
var d = checkArrowKeys(e),
i;
if (d) {
i = directions.indexOf(d);
// remove this direction from the array of directions
if (i > -1) {
directions =
directions.slice(0, i).concat(directions.slice(i + 1));
}
// if no keys are down then stop updating
if (directions.length === 0) {
clearInterval(ti);
ti = null;
}
}
};