JavaScript

requestAnimationFrame lets you schedule “the next frame” at the same timing the screen is about to redraw, so you can make smooth animations or game loops while avoiding unnecessary updates.

requestAnimationFrame

requestAnimationFrame は、画面の描画タイミングに合わせて「次のコマ」を予約できるしくみで、ムダな更新を減らしつつ、なめらかな動き(アニメーションやゲームのループ)を作りやすくしてくれます。

requestAnimationFrame とは?

アニメーションって、パラパラ漫画みたいに「コマ(フレーム)」を素早く切り替えると動いて見えますよね。

requestAnimationFrame(略して rAF)は、その“次のコマ”を ブラウザにお願いして予約するための仕組みです。

つまり、スムーズに動かすのが得意で、ムダな更新を減らしやすいのがポイントです。

正確な説明

requestAnimationFrame(callback) は、ブラウザが次に画面を描画する前のタイミングで callback を呼ぶようにスケジュールします。

呼ばれた callback には引数として高精度な時刻(DOMHighResTimeStamp)が渡されます。

基本形はこれです。

JavaScript

let rafId = 0;

function tick(time) {
    // time はミリ秒(高精度): performance.now() に近い値
    rafId = requestAnimationFrame(tick);
}

rafId = requestAnimationFrame(tick);

止めたいときは cancelAnimationFrame(rafId)

setInterval と何が違うの?

setInterval / setTimeout
“時計”ベースで一定間隔を狙う
ただし描画タイミングとズレることがあり、カクつきやムダ更新が起きやすい
requestAnimationFrame
“描画”ベースで次のフレームに合わせる
アニメ用途で自然、タブ非表示時は間引かれて負荷が下がりやすい

結論:動き(見た目)を更新するなら rAF が基本、定期実行(通信や監視)なら setInterval が向く、みたいに使い分けるのが定番です。

いちばん大事:時間(delta time)で動かす

初心者が最初にハマりやすいのがここです。

こう書けばOK:delta time で位置を動かす(DOM版)

HTML

<div id="box"></div>

<style>
    #box {
        left: 0;
        top: 80px;
        width: 48px;
        height: 48px;
        background: #333;
        border-radius: 12px;
    }
</style>

<script>
    const box = document.getElementById("box");

    let rafId = 0;
    let lastTime = 0;
    let x = 0;
    const speed = 200; // px per second

    function tick(time) {
        if (!lastTime) lastTime = time;
        const deltaMs = time - lastTime;
        lastTime = time;

        const deltaSec = deltaMs / 1000;
        x += speed * deltaSec;

        // 画面端でループ
        const maxX = window.innerWidth - 48;
        if (x > maxX) x = 0;

        box.style.transform = `translateX(${x}px)`;

        rafId = requestAnimationFrame(tick);
    }

    rafId = requestAnimationFrame(tick);

    // 例:3秒後に止める
    setTimeout(() => {
        cancelAnimationFrame(rafId);
    }, 3000);
</script>

ポイント