Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run canvas on background tab

I have recently created a HTML5 canvas animation (also using Processing.js).

The problem is that when I switch the browser to a different tab the animation stops playing.

How can I allow the animation to keep playing while the user is on a different tab than the one containing the animation?

Example: http://jsfiddle.net/EyFTr/3/

If you switch tabs the clock stops, but if you open the link a new window and blur the window the clock will still move.

like image 483
XCS Avatar asked Jun 20 '12 15:06

XCS


3 Answers

The short answer is you can't.

https://developer.mozilla.org/en/DOM/window.setTimeout

In (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2) and Chrome 11, timeouts are clamped to firing no more often than once per second (1000ms) in inactive tabs; see bug 633421 for more information about this in Mozilla or crbug.com/66078 for details about this in Chrome.

Browsers in question are a bit old in that quote but its still relevant. This is by design. Its to reduce processor load when the tab isn't active. (Processing.js uses setTimeout for animations)

Theres a few ways to "fix" this. They involve checking the time, and calculating where the object "should" be based on the time, once the tab becomes active. In your example however though it looks like your code will do that, since its a clock which is based the time anyway.

like image 195
Loktar Avatar answered Sep 30 '22 21:09

Loktar


As Loktar suggested, this symptom could be alleviated by checking the time and figuring out where you should be. Here is a function that could do this:

function smartInterval(func, interval){
    var last = new Date() - interval,
        now,
        numMissed;

    (function iterate(){
        func();

        // compute the number of iterations you might have missed
        // if you tabbed away and the interval was restricted to 1000ms
        now = +new Date();
        numMissed = Math.round((now - last) / interval) - 1;

        // make up for those iterations that were lost
        while (numMissed--) { func(); }

        last = +new Date();
        setTimeout(iterate, interval);
    })();
}

Usage:

smartInterval(function(){console.log('hi');}, 100);

Here is a jsFiddle with an example. Try to comment out the while loop (while (numMissed--)) to see that by switching to a tab, you get less numbers. With the while loop there, however, it appears as if the interval has never changed.

Unfortunately, this might not be of any use to you since you are using Processing.js and the timeouts are set internally.

like image 42
lbstr Avatar answered Sep 30 '22 21:09

lbstr


See setInterval not working properly on Chrome . Essentially browsers will mess around with setInterval when backgrounded to improve performance, so you can't control exactly what happens.

like image 44
Graham Avatar answered Sep 30 '22 20:09

Graham