greensock / GSAP

GSAP (GreenSock Animation Platform), a JavaScript animation library for the modern web
https://gsap.com
19.85k stars 1.72k forks source link

Timeline callbacks at position 0 not firing #7

Closed bjnsn closed 11 years ago

bjnsn commented 11 years ago

When a TimelineMax or TimelineLite has a callback function inserted at position 0 (with .call, .add, or .addCallback) it doesn't fire on repeat or when the timeline has paused and play(0) is called. Callbacks at 0 fired in these situations as of 1.9.1 - but as of 1.9.5 no longer fire.

jackdoyle commented 11 years ago

Good catch - this will be fixed in the next update. If you want an advanced copy, post a request in the forums at http://forums.greensock.com. In the mean time, a simple solution is to place your callbacks at a super small offset from the beginning, like 0.0001.

jackdoyle commented 11 years ago

Resolved in 1.9.6

ianshea commented 11 years ago

Hey Jack - Updated to 1.9.7 and this issue still happens for me.

I am inserting a Timeline into a Timeline. ( Timeline A into Timeline B ) where TL-A has a callback at position 0 and TL-A is being inserted at position 0 of TL-B. Setting a small offset still solves it though.

jackdoyle commented 11 years ago

Hmmm...I can't seem to replicate that behavior. Can you please post a simple codepen or jsfiddle that clearly demonstrates the issue?

ianshea commented 11 years ago

I wrote it out in a codepen and it works just fine. Might be a hitch on the site I'm developing ( which is rather complex ) - I'm not going to worry about it! Please disregard!

Here is the pen if you're interested: http://cdpn.io/pwcxE

artsyca commented 4 years ago

I know this is super old but I'm also experiencing a behaviour on version 3 where the first call to a timeline is only called once on enter and once on reverse but giving it even a miniscule offset will remedy the situation

ZachSaucier commented 4 years ago

@artsyca Thanks for the report! I can produce the described behavior. Minimal demo.

artsyca commented 4 years ago

Nice demo @ZachSaucier --

Chaining the call after the to will remedy the issue, or as mentioned in the code adding like 0.001 to the call so it's telling as to the underlying behaviour but I don't really know enough to troubleshoot beyond that

jackdoyle commented 4 years ago

This should be resolved in the next release which you can preview at https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/gsap-latest-beta.min.js

Better?

artsyca commented 4 years ago

Not sure if it's just my use case but it doesn't trigger when the callback is either at the start of the timeline, at position 0 or inserted using '<' on top of another animation which is at 0

But!! It does now work when the call is the first in the chain

jackdoyle commented 4 years ago

@artsyca are you saying that you tried that new beta file and it didn't work for you? I wonder if you needed to clear your cache. It seems to work fine in a fork of Zach's reduced test case: https://codepen.io/GreenSock/pen/b8c31bf491b13a2489d4d7e7f72789d5?editors=0010

Am I missing something?

If you're still seeing issues, would you please provide a reduced test case? Perhaps a codepen? Thanks!

artsyca commented 4 years ago

Yes in my case I downloaded the attached prerelease script linked above and attached it to my code but the complication is that it's running with ScrollMagic as a tween so perhaps it has something to do with the interaction of these two libraries which is done through setTween(timeline) as opposed to yoyo

Essentially when setting a trigger in ScrollMagic with a timeline that has a call at the start the call will only get called the first time the timeline is triggered and not when it's reversed or triggered on subsequent interactions

you asked for a codepen, here you have a codepen!

https://codepen.io/artsyca/pen/gOaGYyN

Scrolling the div in and out of the scene is meant to trigger the call and it works better than it used to but still requires a slight offset, however this is an improvement because before the call wouldn`t work if it was the first item in the chain even with an offset at least now that's fixed

jackdoyle commented 4 years ago

Oh, that's not a GSAP issue. You've got a zero-duration timeline in your example, so the playhead literally cannot move from the very start. The call() shouldn't get called multiple times in that scenario. See what I mean? It'd get called when the playhead leaves/arrives/passes that spot...but there is no leaving/arriving/passing if the entire timeline is literally zero seconds.

Make sense?

artsyca commented 4 years ago

Yes this is a behaviour of ScrollMagic/GSAP which is documented somewhere in the arcana but I believed it was due to a zero duration scene, not a zero duration timeline, an important distinction -- well noted

I'm very grateful to your help and assistance with these matters and indebted to the GSAP library for some recent client work which simply would not have been possible otherwise -- it's very kind of you to offer such a generous license and I look forward to including GSAP in my professional repertoire

While we're on the subject, is there a way for call to know whether the timeline is running in reverse at the time of the call?

jackdoyle commented 4 years ago

While we're on the subject, is there a way for call to know whether the timeline is running in reverse at the time of the call?

Every tween/timeline has a "reversed()" method that tells you if it's actually reversed...HOWEVER, that only tells you if it's oriented to play backwards in its parent. So if the parent gets reversed and the child is reversed, it'd make the child look like it's playing forward! Plus "reversed()" doesn't tell you if it's a forward-oriented animation that's in its yoyo phase.

Yeah, it can get a little mind-bending.

Here's a method you can feed a tween or timeline to and it'll tell you (in an absolute sense) if it's oriented backward (including if its in a yoyo phase of a repeat):

function isPlayingBackwards(animation) {
    let orientation = 1; // 1 = forward, -1 = backward
    while (animation) {
        orientation *= animation.reversed() || (animation.repeat() && !(animation.iteration() & 1)) ? -1 : 1;
        animation = animation.parent;
    }
    return orientation < 0;
}

Is that what you're looking for?

I'm very happy to hear that GSAP has served you so well on recent projects. That's always so encouraging.

artsyca commented 4 years ago

Yes that's very helpful! I know people always request highly specific features of marginal utility but my keen sense of OCD had me wondering if there were a way to call a function such as

timeline.call(function forward() { ... } , function backward() { ... })

to for example add a class when going one way and remove a class when going the other? This answers my question very satisfactorily with my sincere gratefulness for all your help!