Jump to content
Search Community

Frames vs Time Confusion

swampthang test
Moderator Tag

Recommended Posts

Trying to use tl.set(item,{autoAlpha:1}) on items at specific times. It has all seemed to be working fine but I just noticed recently that, when I step through (calculating frames for each step), autoAlpha doesn't get triggered until the next frame. I'm thinking there may be some Math issue here and wondering if any of you Math wizards might have the answer.

 

WHAT SHOULD HAPPEN:

In my thinking, when masterTL is at the time 0.1, the box should display but it doesn't display until the following frame. But what's even more curious to me is that, when you frame back from 5 to 4, it continues to display. 

 

Any insight would be greatly appreciated. Thanks.

See the Pen mdWJdvJ by swampthang (@swampthang) on CodePen

Link to comment
Share on other sites

Another thing I noticed is that going all the way to the end of the timeline (frame 34) and then back to frame 33 where the box displays, you can click rewind and step forward and you'll see the box on frame 4. I'm wondering if this has something to do with how immediateRender works.

 

Added a TO END button because I also noticed that, before the image ever displays, you can jump to the end masterTL.progress(1) then rewind masterTL.progress(0) then start clicking the frame >> button and you'll see the image on frame 4.

 

One thing to note, frame 1 starts at 0. There is no "frame 0". For example, if the frame rate is 30 FPS, in the video world, the last frame of the video starts 0.03333333333333333 seconds before the end of the video.

Link to comment
Share on other sites

11 hours ago, swampthang said:

In my thinking, when masterTL is at the time 0.1, the box should display but it doesn't display until the following frame. But what's even more curious to me is that, when you frame back from 5 to 4, it continues to display. 

You're bumping into some of the inherent complexities of zero-duration things (.set() calls) in a full-blown timeline system. Animations don't waste time rendering or considering themselves "started" until their playhead actually moves from 0 to something greater than 0. You're putting the playhead directly on top of the zero spot of the timeline's origin. You've put a .set() call right there too, and .set() calls must actually store two states (before and after). So when you land precisely on top, which is it supposed to render? And is the timeline considered "started" if the playhead was at zero and you put it at...zero (no change)? Should it burn resources ripping through all its children and rendering them in that case? 

 

There are actually a bunch of other complexities I won't bore you with that I've learned over the years of tweaking the system. There are a surprising number of edge cases and complexities, particularly with zero-duration things that store two states and a decision must be made about which to render. 

 

Several solutions: 

  1. Pre-render the timeline to force everything to record the starting/ending values up front, like
    // force the playhead to the end and then back to the beginning, skipping any callbacks
    masterTL.progress(1, true).progress(0, true)

     

  2. Use short tweens instead of .set() calls. Any duration, even 0.001, will solve the dilemma of having the playhead land on both the start and end of the tween/set. But of course that means that you'll need to put the playhead at the spot you want, like if you want it rendered at the end values, it might be a time of 0.001 or if you want the starting values, 0. 
  3. Offset your values slightly. Like if you placed tl at 0.0999 instead of 0.1, that means that when you put the playhead at 0.1, it won't be right on top of where it starts, thus the initial state of things that were set() at the beginning will get rendered. 
7 hours ago, swampthang said:

Is running masterTL.time(0.1) as a setter supposed to return the object?

Yep. That's what makes chaining possible. Almost every method is like that. 

masterTL.time(0.1).pause().timeScale(0.5);

It's quite convenient. :)

 

Does that clear things up? 

  • Like 1
Link to comment
Share on other sites

5 hours ago, GreenSock said:

You're bumping into some of the inherent complexities of zero-duration things (.set() calls) in a full-blown timeline system

Makes sense. The option to immediately show/hide something with no in/out animation has been a bit of a brain-twister for me in these situations for some time. You'd think the more challenging stuff would involve actual animations, huh! I'll try the things you suggested. 

 

5 hours ago, GreenSock said:

Does that clear things up?

Yes, Jack. Duh! Thanks so much for the thorough explanation. Sometimes my feeble noggin gets the best of me. 

Link to comment
Share on other sites

For anyone else who might just happen to need to step through their animation 1 frame at a time 😀  here's another way of handling this.

See the Pen qBrdzdp by swampthang (@swampthang) on CodePen

As Jack so eloquently and thoroughly explained...

On 5/9/2021 at 12:45 AM, GreenSock said:

You're bumping into some of the inherent complexities of zero-duration things (.set() calls) in a full-blown timeline system. Animations don't waste time rendering or considering themselves "started" until their playhead actually moves from 0 to something greater than 0. You're putting the playhead directly on top of the zero spot of the timeline's origin. You've put a .set() call right there too, and .set() calls must actually store two states (before and after). So when you land precisely on top, which is it supposed to render? And is the timeline considered "started" if the playhead was at zero and you put it at...zero (no change)? Should it burn resources ripping through all its children and rendering them in that case? 

So, rather than jumping to the end and beginning, just advance 1 frame beyond the next frame and then and back TO the next frame so GSAP knows for sure the box should be displayed.

if (currentFrame + 2 <= totalFrames) {
  // temporarily move 1 frame beyond the next frame to assure set() does display!
  masterTL.progress(currentFrame + 2 / totalFrames);
}

Thanks again to Jack for taking the time to explain the issue. Especially given the fact that this is such an edge case (as most of my issues have been).

  • Like 3
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.
×
×
  • Create New...