Jump to content

Christoph Erdmann

TweenLite.ticker does not work as expected

Go to solution Solved by OSUblake,

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



maybe it's my wrong expectation. :)


I'am using GSAP with three.js this way:

function update() {
	console.log('Update executed');
	renderer.render(scene, camera);

TweenLite.ticker.addEventListener("tick", update); 

In GSAP I have a main timeline with some nested subtimelines.

My expectation is that update() should only be called if a visible animation is running. So if no element is animated update() should not be called. But it is always called. It even keeps running if the main timeline is at its end and the animation is over.

Is this the correct behaviour?


So why should I use the ticker when a simple

var raf = function() { requestAnimationFrame(raf); update(); }

does its job? Is it just to have the ability to set the FPS or am I missing something?





Link to comment
Share on other sites

Yep, that's working properly. 

  1. The benefit of using GSAP's ticker is that it'll always update AFTER the core engine does its updates. If you use your own RAF, that may not be the case. And, like you said, you can set an fps with GSAP's ticker.
  2. We intentionally keep the ticker going even when GSAP animations aren't active because that's what most people seem to prefer - they often have their own rendering logic baked in there that shouldn't suddenly stop when GSAP-specific animations aren't running. They want consistency. And remember, GSAP's ticker is hyper-optimized for performance and part of that means waiting for a little while (typically a max of about 2 seconds) after animations complete before the ticker powers down. (Think of it like keeping your car's engine on/idle at stoplights - turning the car completely off would be overall more taxing and it'd make things less responsive if/when you do need to step on the gas). 

Does that clear things up?

  • Like 1
Link to comment
Share on other sites

1. So, if I use my own RAF it could be the case, that my render frame is skipped and GSAP calculated animations unnecessarily. Or GSAP execution was skipped and my RAF renders the same data a second time, correct?


2. I think I understood but especially in the banner industry you usually have so simple animations that you very often completely rely on GSAP. There it is a little bit counterproductive if the ticks are triggered if nothing changes.

In my case the three.js banner is also rendered when nothing changes or when the animation is complete. Now imagine we have multiple banners on a page which are rendered all the time regardless of something being animated. That could stress the CPU or GPU a lot.


I fixed it a little bit by doing this (that stops rendering at the end of the main timeline):

if (main_timeline.isActive()) {
	renderer.render(scene, camera);

But the ticks are further triggered on pauses between the single scenes. Would be nice to have the rendering stopped then. Is there a way to do this? What about an alternative tick event that takes this into account? What do you think?

Link to comment
Share on other sites

  • Solution

Hi ,


GSAP uses rAF, and if you're calling rAF, that means there will be two calls out for it, which get added to a queue. That means there is no guarantee your call will happen in the same order or frame as GSAP's call. Letting GSAP make the call will help keep your rendering in sync with the objects it updates. You can even prioritize the order in which things get called.


Need to run some logic before GSAP updates? Not a problem. Just add a listener with a positive priority. Need to do some cleaning up after GSAP updates? Just a add a listener with a negative priority.

// Called before update
TweenLite.ticker.addEventListener("tick", preUpdate, this, false, 100);

// Called after update
TweenLite.ticker.addEventListener("tick", postUpdate, this, false, -100);

Don't need those listeners anymore? Remove them.

TweenLite.ticker.removeEventListener("tick", preUpdate);
TweenLite.ticker.removeEventListener("tick", postUpdate);

If there's an active listener on the ticker, it's going to call it. That should be the expected behavior for any ticker, not just GSAP's. I use the ticker for other stuff, like frame based animations or throttling browser events. If GSAP stopped calling any listeners after it was done animating, well that would be bad. GSAP has no way of knowing what I'm using the listener for. 


And you might now even need to use the ticker. You said you were using a main timeline, so you could use its onUpdate callback  to call your render method. That's what I do for simple stuff that doesn't require the ticker to run constantly.


To help get a better understanding of what I just talked about, I made a really simple demo for you. Notice how the listeners are happening in the correct order. If you change their priorities, the count won't come out to zero. And when I'm done with the animation, I just remove the listeners. 

See the Pen d360a2ce841054f74fac985ac7062c44?editors=0010 by osublake (@osublake) on CodePen



  • Like 2
Link to comment
Share on other sites

Thanks for the nice explanation and the example. onUpdate should be what I've been searching for.

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.