1

したがって、グリッドの周りを移動する小さな正方形がありますが、onkeydown イベントを実行すると、正方形が非常に速く移動します。私の小さな正方形がはさみにぶつからないように、10 秒に 1 回だけ実行したいのです。しかし、setTimeout関数を試してみると、最初のキーダウンでのみタイムアウトし、その後も高速に実行され続け、キーを離しても追いつくためにまだ実行されています。これは私の小さな広場にとって非常に危険です。どんな助けでも大歓迎です。

setTimeout 関数を使用しないコードを次に示します。これは、正しい方法ではないと感じているためです。

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]){
        transition(arrs[key]);
    }
}
document.onkeydown=checkArrowKeys;
4

2 に答える 2

1

キーボードの応答は、驚くほど複雑になる可能性があります。通常、発生するすべてのキーダウンイベントに注意を払う必要はありません。これは、ユーザーのキーボードと設定に依存するためです。たとえば、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;
        }
    }
};
于 2012-12-22T22:52:28.520 に答える