Jump to content


possible bug using call at the end of 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 just spent a good few hours trying to work this out and not sure if its a bug or not but thought I would share on here.


I'm using a various timeline tweens with .call() at the beginning and end of each timeline to show and hide an asset. These are used in conjunction with various other tweens in the timeline.


i.e on a 6 second timeline..


.call(showHide, [], this, 0)
.call(showHide, [], this, 6);


These timelines are then chained together in one master timeline.


What I noticed is that while moving forward through the timeline everything worked OK but going backwards the .call() that was at the end of the each individual timeline wouldn't fire.


I solved this by just triggering the call 0.1 of a second before the end of a timeline.


i.e again on a 6 second timeline..


.call(showHide, [], this, 0)
.call(sshowHide, [], this, 5.9);








Link to comment
Share on other sites

It would really help if you created a very basic CodePen demo that clearly illustrates this behavior.

Here is a little info on how to do that: http://forums.greensock.com/topic/9002-read-this-first-how-to-create-a-codepen-demo/


Before doing that, please make sure you are using the latest version of the GSAP files.



Link to comment
Share on other sites

I can see how this might appear to be a bug, but you've actually come across an edge case that demonstrates a conundrum that as far as I can tell is logically impossible to solve (though I welcome suggestions). Don't worry, though, there's a workaround. Let me explain....


Zero-duration "events" on a timeline (which could be zero-duration tweens or callbacks) are tough because the starting and ending positions are identical on the parent timeline, making playhead direction irrelevant. In your case, you put a callback at the VERY END of the sub-timeline. Imagine the virtual playhead reaching the end...it would of course stop at that point (it can't go past the end). Then, if you reversed and made the playhead go backwards, you wouldn't expect that callback to fire AGAIN (because it fired as it reached the end). See the issue yet? 


In your example, the playhead reaches the end of the sub-timeline, but the playhead of the parent timeline keeps going, and eventually yoyo's back, and at some point it intersects with the sub-timeline and starts moving its playhead. So since it was stuck at the end and then started moving backwards, it doesn't fire that callback a second time. 


It would be very easy for me to write the code such that the callback fires again when it starts moving again (backwards), and that's actually the way it worked a LOOONG time ago when I first build TimelineLite, but the big problem was that it was much more common for people to run into situations where the playhead would reach then end, and then get reversed and the callback would fire again when that behavior seemed unintuitive. In other words, a callback should fire when the playhead ARRIVES at that time/frame OR when it LEAVES that time/frame, NEVER BOTH. In your scenario, you're expecting it to do both. That's not to say you're "wrong" or anything, but hopefully you see how it's logically impossible to have both behaviors and that it'd cause problems in more common scenarios if we changed the behavior to fire multiple times like this. 


Not to worry, though. Once you understand WHY this is happening, you can work around it easily. There are actually a few options:

  1. Add a phantom call at the end of the timeline that's slightly offset so that your callback isn't at the very end, like .to({}, 0.00001, {})
  2. You could offset the callback slightly so that it's not at the VERY end of the timeline (maybe use a relative offset of "-=0.00001")....or....
  3. You could use a tween that has a tiny amount of time, and set the onComplete and onReverseComplete to your callback (that's basically what a call() does anyway). 

This is what #3 could look like:

.to(showHide, 0.00001, {onComplete:showHide, onReverseComplete:showHide, onCompleteParams:["red"], onReverseCompleteParams:["red"], overwrite:0})

This is definitely an edge case, since it'd only be an issue if you position a zero-duration child (tween or callback) at the VERY end of a nested timeline that's in a parent that yoyo's. 


Does that clear things up? Sorry about any confusion.

  • Like 1
Link to comment
Share on other sites

Hi guys


Thanks for your replies..


To be honest while not understanding the exact details of why its along the lines of what i figured was happening. I'd already solved the it by doing as you said and not putting the callback right at the end of the timeline.


I posted really just to document it in case anyone else had a similar problem.


But interesting read and to be honest I am constantly impressed at how reliable GSAP is.

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