Jump to content


Animation onComplete & onReverseComplete when used in a timeline

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

Hi! I'm having some issues with the onComplete and onReverseComplete callbacks for tweens of 0 duration added to a timeline.


Generally, they work as I expected, but sometimes they do not get called, or onComplete gets called when onReverseComplete should have been called.


Since they work OK most times, my app kind of relies on them being called at the right times, but I started getting some issues becuase it seems they aren't.


In my app, the animations are created dynamically, so reproducing it is somewhat complicated, but I built and attached an example that shows the issue.


The code goes like:

var valueAnimation = TweenLite.to(
                        0.5, { innerText: 300 }, { innerText: 0 });					
var textAnimation = new TweenLite({}, 0, { 
	immediateRender: true,
	onComplete: function() {
		document.getElementById('button').innerText = "Reverse";
	onReverseComplete: function() {
		document.getElementById('button').innerText = "Play forward";	

timeline = new TimelineLite({ paused: false, autoRemoveChildren: false })

To reproduce it, open the reverse_test.html file and follow the instructions. 


Looking for similar issues, I read that onReverseCompleted was not called on child animations since what is actually reverted is the parent timeline; but the issue is that, most times, it's being called, and I ended up counting on it.


Please, let me know if I can provide any additional info.




Link to comment
Share on other sites

Zero-duration tweens are a very unique beast in a tweening engine because by their very nature, "tweens" imply some sort of duration (time lapse). So if the playhead lands exactly on top of where a zero-duration tween sits, should that be interpreted as the tween beginning or ending? Should the starting values be rendered or ending values? See the dilemma? 


So in GSAP, we attempt to sense the momentum of the playhead and deduce from that which values should be applied. Of course the easy solution would be to make your tweens really short, like 0.001 seconds, but I'd rather not have you resort to that. So I dug into your example (which was very helpful - thank you!) and discovered the issue. It has to do with floating point number rounding in the browser when the playhead landed on a SUPER small time, like 0.000000000001. I believe I've got it worked around now, and I've attached an updated preview version of 1.9.5. I let your example run for about 2000 iterations (the loop option) and it NEVER broke, so I'm pretty confident this is resolved. 


Thanks again for making the example file. 


Oh, and by the way, I noticed 2 things in your code that I thought I'd mention:

  1. You had an extra parameter that you were feeding to a TweenLite.to(). It was as if you were treating it like a fromTo(). You had TweenLite.to(obj, 1, {...}, {...}). Notice the extra {...} in there. 
  2. You were creating your TimelineLite and specifically defining paused:false and autoRemoveChildren:false, both of which are the defaults anyway, so you don't need to do that. No biggie. 


  • Like 2
Link to comment
Share on other sites

You sir, are amazing ;). Works perfectly, saved my day.


Thanks for the additional code comments and the excellent support!

  • Like 2
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.