Jump to content


Fixed time step in gsap ticker?

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts



First of all, thanks for the great work and I (but I belive I speak in the name of the community) thank you for all your hard work that you guys have put on your beautiful product.


I've successfully used TweenMax in past projects in different scenarios (animations, hover effects, games on dom, canvas, svg), but for my current one, I think I might need some extra help :(.


To explain the issue I'm having, first I need to walk you through my environment: I am basically building a slideshow animation on canvas using TweenMax and createjs (to be more specific only the easel.js lib).


Everything works fine, except that at some point the tweens are jerky. In my app,  the browser is doing other things in parallel with the animations and - as expected - this has an impact on the framerate. From time to time the fps drops from 60 to 20-30 and after that it goes back up to 60.

I know that the frame drop is mainly caused by the other things that my app is computing, but of course the effect is more visible on less powerful devices. 

The problem is also described in the codepen attached  (which is obviously exaggerated in order to point out the evident).


Unfortunately, I can't totally separate the logic from the animation and I need to run many things in parallel, so changing the architecture isn't a solution for my problem.


From my research and try-outs, none of the cool stuff you guys are offering is a real candidate as a solution to my problem, and so far I've tried numerous combinations of ticker and animation settings (raf, no raf, different fps speeds, lagSmoothing and  lazy rendering).


After some more research and digging on the net, I'm starting to think that the problem is that I'm approaching the animations like a movieclip: I have a strict duration of time in witch I must go from point A to point B, while I should be approaching them more like a game: moving one step at a time, recalculating positions, velocities and other factors that influence the position of my items on each loop (in our case Timeline.ticker tick event).


In game development, in order to ensure maximum fps while having other important (and probably CPU intensive) logic computed (such as collision detection or multiplayer sync), the most common approach is to implement a fixed time step loop (there are many other useful articles on this on the web, but this was one that explained the solution more clearly). 


I guess that the basic idea is to decouple the logic from the rendering process and try to predict when the next render will occur in order to approximate the position better. This approach seems to be working for most loop-based games (although not too many of them are written in javascript).



I myself tried to implement this approach using my current architecture but failed and in order to not rewrite everything from scratch, I looked into implementing this kind of solution in the gsap animation engine.
While I (clearly) don't know what I'm doing, it seems that this kind of implementation can be either implemented in the core Animation object (as an extra option, just like lagSmoothing) or as a plugin. The latter is more convenient, but from my understanding, plugins are targeting animations and specific parameters, while I would want to be more generic and target a timeline of tweens, not a specific property. 


Now that you've had the patience to read my lines, my questions for you are:

  • Do you consider that having a fixed time step loop solution might fix my problem?
  • Do you have any other suggestion that might help me solve my issue?
  • Can the solution I presented be implemented as a plugin (if yes... could you provide some basic steps?)
  • Have anyone else (because I couldn't find anyone else) suggested this approach for gsap?


I look forward to your answer, because I really want to make this work with gsap and not to have to rewrite all my animation engine from scratch.





See the Pen YPgJMN by gion (@gion) on CodePen

Link to comment
Share on other sites

You might try using force3d even though you're not doing 3D transforms, just to offload some of the work to the GPU.  


I've had a couple of issues like this (with CPU-intensive scripts running in the background) and I've gotten around the issue just using setTimeouts and staggering the tasks -- or pre-calculating required computation .

Link to comment
Share on other sites

Thanks @MindGamer for your input, but I do think that force3d is an option only when it comes to animating css properties. In my case I'm actually animating things in a canvas, so it wouldn't make any difference.

Link to comment
Share on other sites

What about updating your objects in the loop using the actual time? Maybe using something like this...

function getTime() {
  now  = window.performance.now();
  time = (now - last) / 1000;
  last = now;
  return time;
Link to comment
Share on other sites

I just tested out that function in your demo, resulting in a slightly better but much more consistent framerate... at least on my machine.


See the Pen gbyYJG by osublake (@osublake) on CodePen

Link to comment
Share on other sites

Perhaps I'm misunderstanding, but I really don't think there are any other [better] options than what GSAP already gives you. As the article described, there are two ways of handling updates - either time-based, or frame-based (GSAP offers both, by the way). If you prioritize time, you're more likely to see jumps/skips during the animation when the CPU is overwhelmed. If you use frames, your animations will literally slow down when the processor is bogged down. There is no magical way to get around it - you must pick your poison. 


Interestingly, lagSmoothing() delivers a hybrid approach (kinda) where you can set a threshold for time-based animation beyond which it'll make a correction and slow things down only in that case (typically to avoid big jumps). 


Also keep in mind that the article you referenced is written specifically for games where there's iteration-based logic, like "on each tick, add ___ to the velocity and calculate ___, etc." but that's not at all what GSAP does. We built it to be free from that kind of iterative logic that gets messed up when the CPU bogs down. GSAP is time resolution independent. But if you want a system where each tick has a certain amount of time delta regardless of how fast the ticks are generated, you can simply set useFrames:true on your tweens and set the durations/delays to the number of frames you want them to take. I have a sneaking suspicion that's the effect you're after here, but I could be wrong. 


Again, maybe I'm missing something; let me know if I am :)

  • Like 3
Link to comment
Share on other sites

First of all, I want to thank you guys for the replies.
I didn't have time to respond because I was busy implementing a solution :).


@OSUblake: thanks for your suggestions, I took a look into that approach. I actually ended up hijacking the ticker's callback and recalculating my desired progress based on my own time calculations.  As for the demo, I really didn't see any significant improvements.


@Jack: I was expecting this kind of answer and you may be right: TweenMax was built to make sure you don't have to interpolate environment values on each tick.

And yes, TweenMax does offer a frame based animation system if you feel that the default (time based) one doesn't suit your need.

Please correct me if I'm wrong, but from my research & tests, here's what I understand that TweenMax has to offer:

  • a time based animation mode that guarantees it will be finished in the exact amount of time it is specified, but it may actually skip some frames if the browser decides to drop the frame rate (delta S is irregular):
  • a frame based animation mode that guarantees that it will go through each frame (no skipping) but doesn't sync with any duration. It fully depends on the render cycle: if the browser's frame drops, the speed of the animation will drop too:

If you look at the two animation modes you can see how they are different and that they are a valid solution for different kind of situations:

My situation implies that in order to reduce animation jerkiness I need to draw as many frames as possible (like in the frame based animation) but  not necessarily at a fixed step. I see this normalization of the tick values as a hybrid between the two: 


I know that this is probably not something that GSAP has planned to deliver, but it seems to be the solution in my case.


If you're curious, you can see some test results on this codepen: 

See the Pen qEwRLj by gion (@gion) on CodePen

I'm currently still working on the solution, so I can't actually post any code, but, as soon as I have a stable prototype that really is an improvement for my demo, I want to share it and probably get some help from you guys to make it as a plugin. 


Thanks once again for your input!

P.S.: sorry for the big pictures, I thought that they could be resized in this wyswyg editor.

  • Like 1
Link to comment
Share on other sites

I love the graphs/visuals, thanks.


So are you saying you're trying to split the difference? For example, if "normal" is 16ms between ticks, but the processor gets bogged down and it takes 32ms, you want it to act like there was 24ms? So it slows down...but not quite as much as useFrames? It neither prioritizes absolute time, nor a steady delta...it sacrifices both? 


From my understanding of the data out there, the most significant problem that the human eye notices is variance in frequency of updates (fps), not so much the delta on each and every tick individual tick or how far things move. So I worry that all this effort in splitting the difference may not really make much of a difference perceptually, and you'd get a better "looking" animation if you just dropped the fps to 30 so that the CPU has more breathing room and the updates are made at a more consistent, reliable rate. 


But if you find a solid solution, we'd love to see it. Thanks for the detailed explanations. 

Link to comment
Share on other sites

I just want to say that I appreciate the graphs. Very helpful.

Link to comment
Share on other sites

  • 3 weeks later...

Hey guys,


I want to say that I appreciate your input and that you were right: the direction I was going to was far off what gsap was intended to implement.

My prototype didn't have the results I was expecting and I did had a smoother experience just by reducing the framerate (although it didn't actually solved any problem).


If I ever get any new directions on this topic, or if anyone else buzzes something in this area, I will be more than happy to see/share new ideas.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.