1. ホーム
  2. javascript

[解決済み] requestAnimationFrameでfpsを制御する?

2022-05-07 17:32:49

質問

と思われます。 requestAnimationFrame は、今やアニメーションのデファクトである。しかし、今、私はキャンバスのアニメーションをしようとしていて、疑問に思っていました。ある一定のfpsで動作するようにする方法はないのでしょうか?rAFの目的は一貫して滑らかなアニメーションであることは理解していますし、私のアニメーションが途切れ途切れになる危険性もありますが、今はかなり任意に極端に異なる速度で動作しているようです。

私なら setInterval しかし、私はrAFが提供する最適化(特にタブにフォーカスが当たったときに自動的に停止する)が欲しいのです。

私のコードを見たい人がいるかもしれないので、一応書いておきます。

animateFlash: function() {
    ctx_fg.clearRect(0,0,canvasWidth,canvasHeight);
    ctx_fg.fillStyle = 'rgba(177,39,116,1)';
    ctx_fg.strokeStyle = 'none';
    ctx_fg.beginPath();
    for(var i in nodes) {
        nodes[i].drawFlash();
    }
    ctx_fg.fill();
    ctx_fg.closePath();
    var instance = this;
    var rafID = requestAnimationFrame(function(){
        instance.animateFlash();
    })

    var unfinishedNodes = nodes.filter(function(elem){
        return elem.timer < timerMax;
    });

    if(unfinishedNodes.length === 0) {
        console.log("done");
        cancelAnimationFrame(rafID);
        instance.animate();
    }
}

Node.drawFlash()は、カウンタ変数に基づいて半径を決定し、円を描画するいくつかのコードにすぎません。

解決方法は?

requestAnimationFrame を特定のフレームレートにスロットルする方法

5 FPSでのスロットリングのデモ。 http://jsfiddle.net/m1erickson/CtsY3/

このメソッドは、最後のフレームループを実行してからの経過時間をテストすることで動作します。

描画コードは、指定したFPSの間隔が経過したときにのみ実行されます。

コードの最初の部分では、経過時間の計算に使用するいくつかの変数を設定します。

var stop = false;
var frameCount = 0;
var $results = $("#results");
var fps, fpsInterval, startTime, now, then, elapsed;


// initialize the timer variables and start the animation

function startAnimating(fps) {
    fpsInterval = 1000 / fps;
    then = Date.now();
    startTime = then;
    animate();
}

そして、このコードが実際のrequestAnimationFrameループで、指定したFPSで描画を行います。

// the animation loop calculates time elapsed since the last loop
// and only draws if your specified fps interval is achieved

function animate() {

    // request another frame

    requestAnimationFrame(animate);

    // calc elapsed time since last loop

    now = Date.now();
    elapsed = now - then;

    // if enough time has elapsed, draw the next frame

    if (elapsed > fpsInterval) {

        // Get ready for next frame by setting then=now, but also adjust for your
        // specified fpsInterval not being a multiple of RAF's interval (16.7ms)
        then = now - (elapsed % fpsInterval);

        // Put your drawing code here

    }
}