Synchronized animation after toggling between browser tabs or applications

Hei there. I noticed this issue before in some of my graphics: Please have a look at this infographic about cannabis use. Wait until the end and look at the smoke. The smoke is built out of one symbol that starts a couple of instances of another symbol on its part at staggered intervals. Everything´s fine, but - when I go to another browser tab or toggle between applications and come back to the infographic tab the animation gets more and more synchronized - means: in the end there are no intervals left. The threads of smoke start all simultaneously. Weird... :thinking:

Just try it on your own: (15.2 KB)

1 Like

I would suggest taking the start timeline action out of the raunch symbol and putting a single one on the smoke symbol main timeline (18.3 KB)

1 Like

The issue is that when a webpage isn't shown (like showing a different tab), then JavaScript stops. When the page is shown again, then the animation needs to look at the large time difference and decide what to do.

In this case, all the running timelines are long past their end. So all of them run through their actions to catch up, which has a start timeline on them. Therefore, all timelines are now starting at the same time.

The way to fix this on Hype's end would be to tick through every missed frame of time. Basically, to run it like in real time, but as fast as it can. This could be very computationally expensive leading to long hangs (or even crashes on iOS) when returning to a page. People sometimes return to pages after days or even weeks, so that makes this solution infeasible in a lot of cases. Also, if there's the case that if animation frames take a while to render (perhaps longer than one frame's worth of time), it may never catch up.

Due to the interactive nature of Hype, there's no great solution on the Hype side for the problem you're hitting unfortunately. I think @MarkHunte's solution is the way to go :slight_smile:.


Thank you Mark and Jonathan for analyzing this. Marks solution doesn´t really fit my needs, since it creates a gap after each cycle. Therefore it was a a conscious choice from me, triggering the Symbol-Timelines inside each smoke symbol and make them independent from each other and from whats going on on the Main Timeline. This results in a much smoother animation process (I often come across this problem, e.g. when simulating rain, hail etc...).

The issue is that when a webpage isn't shown (like showing a different tab), then JavaScript stops.

... but why should the repetitive startTimeline command on the Main Timeline work then? Obviously it does...

So I chose a different approach: I initially start an setInterval for each smoke symbol - and surprise - it works! :grinning: Hence, JavaScript doesn´t seem to stop completely - at least the setIntervals keep on working... (20.0 KB)

1 Like

My answer was perhaps an oversimplification :slight_smile: . Hype generally uses requestAnimationFrame which typically does not fire when a tab is hidden. Other timers like setInterval/setTimeout are usually highly curtailed and not guaranteed. This documentation seems to indicate most browsers put their max fire rate at 1 second. I'm not sure this is spec'd though - I'd guess browsers change behavior a lot in efforts to conserve battery life. Of course, Hype has some uses of setTimeout for various things as well, so there's probably a smidge of hodge-podge behaviors...

Regardless I'm glad you found a solution!

1 Like

I do not think the set intervals version is working as you expect. ( if I am honest I am not surprised as setIntervals can easily get out of sync )

Yep, you´re right concerning Safari. For me it works perfectly in Chrome and even in Edge, Firefox has slight glitches but works in principle. Funny...

I think, this version gives me the best result in all Browsers... (16.3 KB)

1 Like

I see,
The counter is now doing a reset, when the get out of sync they should reset and only briefly be out of sync.

This may help, I remembered I have used in the past

Document: visibilitychange event - Web APIs | MDN

This way you don't get the glitch before reset.

We fire the visibilitychange init code (initVisibility function) On Prepare For Display.

smoke_scripted_MHv2 (19.7 KB)

The smokeCompl symbol also has the class name of mainSmoke

initVisibility function

	const mainSymbol = document.querySelector('.mainSmoke')
	const 	mySymbol = hypeDocument.getSymbolInstanceById(	
	var hidden, visibilityChange; 
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support 
  hidden = "hidden";
  visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
  hidden = "mozHidden";
  visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
  hidden = "msHidden";
  visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
  hidden = "webkitHidden";
  visibilityChange = "webkitvisibilitychange";
	document.addEventListener(visibilityChange, handleVisibilityChange, false);
  function handleVisibilityChange() {
 		hypeDocument.customData.hidden = //
	console.log (document[hidden])
	if (document[hidden]){
	 	console.log ("stopping")
  		mySymbol.pauseTimelineNamed('Main Timeline', hypeDocument.kDirectionForward);
  		mySymbol.goToTimeInTimelineNamed(0, 'Main Timeline')
  		counter = 0;
	} else {
		console.log ("starting")
	mySymbol.startTimelineNamed('Main Timeline', hypeDocument.kDirectionForward);

That´s perfect, Mark! Works like a charme! Thanks a lot for that!!