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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With