Jump to content
Search Community

Why return Timeline ?

PaulTheSwissGuy test
Moderator Tag

Recommended Posts

Hello people, I'm studying the GSAP library and something looks very strange to me.

It's when we create a Timeline in a small function, to return them in one big timeline.

I understand the idea, but when we create a Timeline and add a Tween to it, it will play itself, like this :
 

 
function addTL(){
    const tl = gsap.timeline();
 
    tl.to('.cube', {x: 550duration: 10.4});
 
    return tl; // Why return it ?
}
addTL()
// The Timeline will run 


If I execute addTL(), the tl will execute and the cube will move.

So why i'm seeing something like this on the internet ?

 

function addTL(){
    const tl = gsap.timeline();
 
    tl.to('.cube', {x: 550duration: 10.4});
 
    return tl;
}
 
function fullTL(){
 
    const tlFull = gsap.timeline();
 
    const addGsapTL = addTL();
    // The addTL is running right there, it's not waiting to be added to the tlFull.
    
    
tlFull
    .add(addGsapTL)
}
 
fullTL()


Even more strange, I saw a course from the "IHateTomatoes" guy, and he's doing what I just told you, he's even returning the "fullTL".

Something like this.
First, creation of the two TL Functions (previous and next TL) :

 

 
function createTimelineIn(directionindex) {
  
    const tlIn gsap.timeline();
    tlIn .to(element, {
     // some stuff
    });
 
    return tlIn ;
  }
  function createTimelineOut(directionindex) {
  
    const tlOut gsap.timeline();
    tlOut .to(element, {
     // some stuff
    });
 
    return tlOut;
  }

 

And then that strange move to assemble them.
 

 function transition(directiontoIndex) {
 
    const tlOut = createTimelineOut(directioncurrentStep);
    const tlIn = createTimelineIn(directiontoIndex);
    // The TL are running right now ?
 
    tlTransition.add(tlOut).add(tlIn);
    // This does nothing ?
 
    return tlTransition;
    // and why that final return ?
  }


I'm pretty sure i've missed something in the understanding of the Timelines.
Are they objects or methods ?
Are they executing themselves when we add something to it ?
And why return them, and why even return the final Timeline ?

Thank's if someone is passing by, have a nice day 
✌️

Link to comment
Share on other sites

Hey Paul. I talk about why it's helpful to modularize animations using functions that return timelines and provide some examples in my article about animating efficiently. I think that can help your understanding a good bit.

 

As for whether or not timelines are played immediately upon creation or not, the answer is it depends. Similar to tweens, if you just create them and do nothing else they will play. But if you add them to a timeline, they won't play immediately (unless the playhead of the timeline that they're added to is at the point when they should play). Does that make sense?

 

Let us know if you have more questions.

Link to comment
Share on other sites

Hey Zach, thank's for the info.

It starts to make sense but now a huge "how" comes to my mind.

How can you detect if a Timeline is added to another Timeline before its execution ?

 

Like here :

 

 

  function createTimelineIn() {
  
    const tlIn = gsap.timeline();
    tlIn.to(element, {opacity: 0, duration: 0.4});
 	// The tlIn is actually executed HERE when we call it below in the "transition" function.
      
    return tlIn ;
  }

 

function transition() {
 
     const tlIn = createTimelineIn();
    // How the "tlIn" timeline is not running now ? I'm executing the createTimelineIn(), it should 
    // run the timeline from the body of the function like I commented above
 

	const tlTransition = gsap.timeline();
      // How the timeline "tlIn" wait till here to know if it is added to a timeline ?
	tlTransition.add(tlIn);
 
    return tlTransition;
    // and why that final return ? The "tlTransition" should execute with or without return, just by calling the function "transition()"
  }
    


Sorry but I like to truly deeply understand something when I learn it.
Could you explain the different questions I wrote you in the code above ?

When we call a method in JavaScript it executes instantly,  it does not wait.
It doesn't make sense to me, I must have overlooked something but I don't know what ...

Have a good day/evening ✌️
 

Link to comment
Share on other sites

I think it might help if you read this page of the docs: https://greensock.com/docs/v3/GSAP

 

Every timeline is placed into a parent timeline (except the globalTimeline, of course). When you first create a timeline, it gets placed onto the globalTimeline. I think you might be misunderstanding what it means to "play" a timeline. Every tick (roughly 60 times per second), the globalTimeline updates its playhead and that pulses down through all the attached timelines/tweens to update their playheads. When you first create an animation, no time has elapsed yet, so its playhead won't move until the next tick. 

 

It sounded like maybe you assumed that a timeline fully played before the next line of JavaScript executes, but that's not at all how it works.

let tl = gsap.timeline(); // placed on the gsap.globalTimeline
let master = gsap.timeline(); // also placed on the gsap.globalTimeline
tl.to(...); // we can add whatever animations we want. 
// none of the animations do anything yet because the playhead hasn't moved.
master.add(tl); // tl is removed from the globalTimeline and placed into master.

So for example, if we console.log(), then create a 10-second long animation, and then on the next line of JS we console.log() something, it's not as if the 2nd console.log() happens 10 seconds later....

console.log(Date.now());
tl.to(".box", {scale: 3, duration: 10});
console.log(Date.now()); // this is NOT 10 second later!!

Think of it more like you're just creating animation instructions on that line, you're not actually DOING the animations.

 

As for why you'd return the animation from inside your function(s), that just lets you pass things around and nest things if you want to - it isn't like the return statement makes your animation execute. 

 

function coolAnimation() {
  let tl = gsap.timeline();
  tl.to(...);
  return tl;
}

let master = gsap.timeline();
master.add(coolAnimations()); // takes what is RETURNED from the function and puts it into the master timleine

I hope that clears things up. 

 

9 hours ago, PaulTheSwissGuy said:

How can you detect if a Timeline is added to another Timeline before its execution ?

Are you asking how to determine if one timeline is another timeline's parent? 

if (timeline1.parent === timeline2) {
  // yep
}

Is that what you mean? 

  • Like 3
  • Thanks 1
Link to comment
Share on other sites

  • 2 weeks later...

Wow ! Thank you for that, I was misunderstanding it so much !

I was thinking, like you noticed, that everytime you create a tween or a timeline, it gets played right after it.
But now I understand that it get stored into a timeline or into the global timeline, and then the global timeline got played 60~~ times with requestAnimationFrame() (I guess);


But then a question comes to my mind, when the global timeline runs ? At the end of the JavaScript file ?
How the global timeline knows that there won't be more tweens or timelines to add and it can start to move the playhead ?



 

Link to comment
Share on other sites

30 minutes ago, PaulTheSwissGuy said:

when the global timeline runs ? At the end of the JavaScript file ?
How the global timeline knows that there won't be more tweens or timelines to add and it can start to move the playhead ?

The global timeline is always running. It updates its playhead roughly 60 times per second. When the browser runs your JavaScript that creates your tweens/timelines, that happens BETWEEN those updates. So even if you had 10,000 lines of JavaScript that gets executed, think of that like a "blurb" that does whatever it does, and then the next time the global timeline updates, it just acts on whatever is there at the time. So if that 10,000 lines of JS created 4,000 tweens or something, the'd ALL have exactly the same start time even if it took a full 2 seconds to execute all that [creation] code. 

 

Does that clear things up? 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

I wanted to say when the global timelines starts? (sorry for the poor english)

 

If I fill it up with tweens and timelines during the execution of my scripts, it must start at a certain moment, after it, It can't be fed while running ?
 

Is the global timeline detecting the end of all my script and then starts the 60 fps lifecycle recursion, to start only after being fed up with tweens and timelines  ?

 

1 hour ago, GreenSock said:

When the browser runs your JavaScript that creates your tweens/timelines, that happens BETWEEN those updates.

For me that sentence means that a tween or timeline can get stored between two fps, and then played right away since :

1 hour ago, GreenSock said:

The global timeline is always running.

 

 

In my head it looks like that :
 

const globalTimeline = []
 
function globalTimelineAnimation(){
    // run the playhead 60fps
}
 
function globalTimelineTick(){
 
    globalTimelineAnimation();
 
    requestAnimationFrame(globalTimelineTick)
 
}
 
// simulation of tweens added to the globalTimeline, (gsap.to());
globalTimeline[0] = {tween1}
globalTimeline[1] = {tween2}
 
// Run the global timeline at the end of the script, after being filled up
globalTimelineTick();


Sorry for the inconvenience but I'm really trying hard to understand it, also I'm not new to JS so I don't get why I'm struggling with that.
Thank's for your patience.

Link to comment
Share on other sites

7 hours ago, PaulTheSwissGuy said:

I wanted to say when the global timelines starts? (sorry for the poor english)

It starts pretty much when GSAP loads. 

 

7 hours ago, PaulTheSwissGuy said:

If I fill it up with tweens and timelines during the execution of my scripts, it must start at a certain moment, after it, It can't be fed while running ?

When you create a tween, it records its startTime as whatever the current time is of the globalTimeline (well, unless there's a "delay" of course). So let's say the global timeline is at exactly 2 seconds when you create 10,000 tweens. ALL of those tweens will have their startTime set to 2 (seconds). That's where they're placed on the global timeline. It doesn't matter if it took 100ms of processing time to create all those tweens - they're all created on the same tick, so they'd all have exactly the same startTime. This is a very GOOD thing, trust me. 

 

Then on the very next tick (requestAnimationFrame), the globalTimeline updates its playhead. Let's say it took 0.1 seconds since the last tick (because you had 10,000 tweens created which took quite a while for the browser to execute that JS). All those tweens would now have their playhead moved to 0.1 seconds (synchronized perfectly with the global timeline). 

 

When a timeline updates its playhead, that affects ALL of its children - it moves their playheads accordingly because they're all synchronized. It's like a pulse that goes down through all the children...and children's children, etc. (you can have nested timelines as deep as you want). 

 

I'm concerned that you seem a little stuck on this concept of "it must start at a certain time" or "I can't feed in tweens/timelines while it's running", but that isn't true. The global timeline is always running and you can feed in tweens/timelines anytime. They just get placed at whatever the current time is. Or if they have a delay, their startTime is pushed out further into the future. 

 

Is that making things more clear? Did you happen to read the docs page I referenced? https://greensock.com/docs/v3/GSAP

  • Like 4
Link to comment
Share on other sites

After a long bicyle hike I get where I was wrong, it was about the understanding of requestAnimationFrame() !
 

I tried a simple test with it and I saw that the RAF method is waiting to add tweens before running again (exactly what you were explaining to my dummy brain in the previous messages 😄).

I did that test if someone is passing by

function recursion(){
 
    console.log("Global timeline start");
    
    requestAnimationFrame(recursion)
}
recursion()
 
console.log("+ TWEEN");
console.log("+ TWEEN");
console.log("+ TWEEN");
console.log("+ TWEEN");


So now thanks to your huge help and patience, I know that Tweens and Timelines do not execute themselves right away, they go in a globalTimeline.

 

I can modularize timelines into little functions, which is pretty handy.


And also that even if I have 10000 tweens in a row(just for the example), they will all start at the same time, thanks to RAF() running only after executing all that code.
 

You're the best Jack thank's 🏄‍♀️
 

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