Home > Software engineering >  constant `requestAnimationFrame` frame rate drops suddenly when losing focus
constant `requestAnimationFrame` frame rate drops suddenly when losing focus

Time:10-23

I want a constant requestAnimationFrame frame rate. So we have this:

var stop = false;
var frameCount = 0;
var fps, fpsInterval, startTime, now, then, elapsed;

startAnimating(30);

function startAnimating(fps) {
    fpsInterval = 1000 / fps;
    then = window.performance.now();
    startTime = then;
    console.log(startTime);
    animate();
}


function animate(newtime) {

    // stop
    if (stop) {
        return;
    }

    // request another frame

    requestAnimationFrame(animate);

    // calc elapsed time since last loop

    now = newtime;
    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 fpsInterval not being multiple of 16.67
        then = now - (elapsed % fpsInterval);

        // draw stuff here


        // TESTING...Report #seconds since start and achieved fps.
        var sinceStart = now - startTime;
        var currentFps = Math.round(1000 / (sinceStart /   frameCount) * 100) / 100;
        console.log(currentFps   " fps.");

    }
}

But the issue is if you loss your focus on the page and minimize your browser wait seconds and come back to the window again the frame rate drops suddenly. But we want a constant frame rate right?

How do you fix this?

CodePudding user response:

If you want a constant rate, then requestAnimationFrame is not what you want.

requestAnimationFrame will do its best to execute your callback before the next painting frame, and to not call it when it's not necessary, e.g if your computer is too busy to perform a render, or if your page is not visible to the user.
So indeed, when the tab hasn't the focus, no callback will be fired, but even when it has the focus, you can't expect a stable rate, anything happening on the user's computer can prevent the browser from rendering the page at the expected time, and every user may have a different frame-rate based on their monitor's settings.

There are a few hacks to keep a constant timer even when the page is in the background (e.g using Web Workers, or the Web Audio API), but they won't be able to avoid the issue of the thread being blocked by another app, and these are hacks and may stop working at any time. Moroever you don't seem to need it.

From your description, all you need is to embrace the fact that you don't have a stable rate, and update your animation accordingly.
For this, refactor your code so that it uses a delta-time, as exposed in this answer of mine. This way, you don't need to worry about the actual frame rate, you can be sure that what we see at any given time is at the position it should have been.

CodePudding user response:

as per MDN :

requestAnimationFrame() calls are paused in most browsers when running in background tabs or hidden s in order to improve performance and battery life.

You can't rely on requestAnimationFrame() if you want to do things while the tab is in the background.

  • Related