Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
celli

Master TimeLine and the use of Functions

Recommended Posts

This was mentioned in the GSAP seminar yesterday, as well as from a previous thread that Jonathan and I had this week--and I am curious to learn WHY I would wrap each separate timeline in a function when adding them all to a master-timeline ?

 

I use the master-timeline technique for almost every project, but I do not necessarily wrap each separate timeline in a function--instead I label each timeline variable uniquely, as opposed to wrapping each timeline in a function and naming each function as we see in the code below.

 

What are the advantages to wrapping each timeline in a function, and using the 'return' ?

function carMove(){
var tl = new TimelineMax();
tl.to("#car", 2, {x:"+=200"})
/* more tweens go here */
return tl;
}

function wheelsRotate(){
var tl = new TimelineMax();
tl.to("#wheels", 2, {rotation:"+=360"})
/* more tweens go here */
return tl;
}

masterTL
.add( carMove())
.add( wheelsRotate());
Link to post
Share on other sites

Hello celli,

 

When you set it up this way you allow yourself to reuse various parts of your animation. Because once you start building your animation, things can get quite complex. So by doing it this way your function will return your timeline with the GSAP add() method. This allows you to just change those parts of your animation, instead of having to change everything to accommodate those changes. Then you just change the position parameter  within your master timeline masterTL.

 

The GSAP add() method accepts a tween, timeline, callback, or label (or an array of them) to the timeline.

 

http://greensock.com/docs/#/HTML5/GSAP/TimelineMax/add/

 

If you go to the homepage. The main homepage banner is made this way.

 

Look at the code comments in this GreenSock codepen:

 

See the Pen yhEmn by GreenSock (@GreenSock) on CodePen

 

This is the recommended way to setup and manage multiple nested timelines in GSAP by GreenSock. It gives you the best control for managing your animation, and makes adding or removing much easier. By doing this you can have all your other parts of the animation separated and have one master Timeline, just you would have if you were creating an animation in Adobe Flash.

 

Doing it this way guarantees you have a manageable timeline that will be easier to maintain and manage as your animation grows and becomes more complex! And gives you the ability to seek() and set up a scrubber to further test your animation, like in the Home Page banner.

 

GSAP add() method: http://greensock.com/docs/#/HTML5/GSAP/TimelineMax/add/

 

:)

Link to post
Share on other sites

Thanks Jonathan! I agree... I use this method to add and break up the animation into separate sequences--I am wondering specifically about why we wrap each timeLine in a function ? I use seperate timelines and then run a MasterTimeline using this method, but I haven't been wrapping each timeLine in a function! Why is it better to wrap each timeLine in a function ?

Link to post
Share on other sites

The function creates separation when it returns the timeline when called. That is perfect because the add() method will accept the function that returns the timeline. The function also helps with code management and allows you to reuse specific parts of your animation.

 

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions

 

Functions are great for creating reusable code, and are very useful.

 

If your doing a small animation then you don't really have to do it like the above example with functions and add().

 

But when creating a larger animation, its a great way to do it that way. Especially since Jack and Carl recommend that way, which helps create a best practice when creating nested timlelines, making it fun and easier to manage.

 

:)

  • Like 3
Link to post
Share on other sites

that is great, thank you for the explanation!

Link to post
Share on other sites

Jonathan explained it very well (as usual). 

 

I personally find it much more flexible and easier to read when I break my animations down into modular chunks that are wrapped in their own intuitively-named functions. I can re-order things easier that way in the master timeline too. 

 

If you have a super-long block of code that's all adding stuff to a single timeline and it's all label-based, you often end up with defining positions like "myLabel+=0.2" and "myLabel+=0.5" which is fine, but if you wrap it in a nested timeline that's built inside of its own function, you can just use absolute times in there, like 0.2, 0.5, etc. I find it easier and less error-prone to experiment with the timing in that manner. The timings aren't dependent on anything "earlier" - you just have to worry about that one modular chunk of animation and then you drop the whole piece into the master animation and slide it around wherever you need it. 

 

But really, it's fine to do it whichever way you're most comfortable. 

  • Like 2
Link to post
Share on other sites

Celli, I read you question a little differently. it seems you are already using a modular approach, it's just that you are doing

var first = new TImelineLite();
var second = new TimelineLite();
var third = new TimelineLite();

master.add(first);
master.add(second);
master.add(third);

and want to know why its better to do

function getFirst() {
  var tl = new TimelineLite();
  tl.to(...)
  return tl;
}

function getSecond() {
  var tl = new TimelineLite();
  tl.to(...)
  return tl;
}

function getThird() {
  var tl = new TimelineLite();
  tl.to(...)
  return tl;
}

master.add(getFirst());
master.add(getSecond());
master.add(getThird());

The end result of both techniques is going to be identical and both offer a modular approach. However, wrapping your timelines in a function has two advantages which may not be applicable all the time, but its nice to have them:)

 

1: By using functions to create your timelines, you can create them "on-demand" only when needed. In the context of a large game or application the function-wrapped way means you don't have to create 500 timelines in advance, you can just call the proper function when you need a timeline. 

 

2: You can create the same timeline multiple times and add each unique copy of the timeline to the same or any parent timeline. Although it isn't always necessary, it is very easy to use the function-wrapped technique to do

master.add(getFirst());
master.add(getFirst());
master.add(getFirst());
master.add(getSecond());
master.add(getSecond());

When it comes to doing elaborate, dynamic scene changes (based on user interaction) it makes things incredibly flexible.

Imagine your app has a variety of scenes, and each scene has its own timeline for animating in and out.

You could do something like:

navTimeline.add(scene1Out());
navTimeline.add(scene3In(), "-=1");

which would trigger the timeline that the scene3In() function generates 1 second before the scene1Out animation ends.

 

and then maybe later the user wants to go back to scene1

navTimeline.add(scene3Out());
navTimeline.add(scene1In(), "-=1");

The end result of this technique is that you can generate your transition timelines whenever you need them, as many times as you need them, and glue them together in any number of ways. 

  • Like 5
Link to post
Share on other sites

If I could 'double like' that response, I would!

Link to post
Share on other sites

Hi Jack and Carl,

 

I joined in one of your web seminars about the modular approach recently and it's great, however I'm having a bit of an issue with my 'set' at the beginning of each function. Each 'frame' in the html has a wrapping div, e.g.

<div class="frame frame0">
    <svg class="carton-upsidedown" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 70 190">
        ...svg paths in here...       
    </svg>
</div>

.frame in the css has 'visibility:hidden;' so that the frames are all hidden until 'requested' in the timelines. So frame0 would start by setting its visibility to visible, run the animations and when done set that frame hidden. Then frame1 would become visible, animate, set to hidden, and so on. My assumption here is that for performance only the assets that are required for that animation are 'displayed' and painted in the browser. However, when you run the animation for the first time, frame1 has visibility visible at the same time as frame0 so you get assets from both frames displayed at the very beginning which is not what I expected. Checking in dev tools I can see that frame1's element.style has been set by GSAP to be visible even though frame1's timeline hasn't begun yet. After the animation has run it's full course and I scrub the animation back to the beginning using my html slider for previews, it works as expected. Am I making any bad assumptions here with my 'set's so it doesn't work as I expect on first run of the animation?

I hope my description of my issue is ok ;-) I'm trying to setup a framework for our studio for DoubleClick banner ads, for quick reuse. I would add a codepen to show the full thing in it's glory but I can't publicly reveal the banner animation just now incase I annoy the client.

 

Cheers!

 

Pete.

/*  ==========================================================================
    START ANIMATION
    ========================================================================== */  

    var tl = new TimelineMax();

 /* Frame 0
    ========================================================================== */  

    function frame0() {
        var tl = new TimelineMax();
        tl.set(".frame0", {visibility:"visible"}) // set frame container visible
          .fromTo(".carton-upsidedown", 1.0, { x: 753, y: 50, rotation: 155}, { x: 573, y:-169, rotation: 30, delay: 0.4, ease: Power2.easeInOut})
          ... and so on
          .set(".frame0", {visibility:"hidden"}); // hide frame container
        return tl;
    }

 /* Frame 1
    ========================================================================== */  

    function frame1() {
    	var tl = new TimelineMax();
    	tl.set(".frame1", {visibility:"visible"}) // set frame container visible
    	  .from(".fresh", 0.6, {scale: 0.5, ease: Elastic.easeOut.config(0.8, 0.5)}, "-=0")
    	  .from(".carton", 0.6, {scale: 0.5, ease: Elastic.easeOut.config(0.8, 0.5)}, "-=0");
          .set(".frame1", {visibility:"hidden"}); // hide frame container
    	return tl;
    }

 /* Add frame timelines to main Timeline
    ========================================================================== */  

    tl.add(frame0())
      .add(frame1());


/*  ==========================================================================
    END ANIMATION
    ========================================================================== */  
Link to post
Share on other sites

Also I noticed in your seminar that you used a combination of both TimelineMax and TimelineLite in your code. Any particular reason for this?

Link to post
Share on other sites

Hey Barman,

 

Let me jump into this as I think the GODS of code are not around just now. The .set() method causes a bit of confusion to people because of it being a zero-duration tween.

 

Have a look at this other topic - It is the same issue you are having. And there's a little video there to boot. ;)

 

http://greensock.com/forums/topic/14328-tweenmaxset-moves-to-beginning-of-timeline/?hl=immediate+render#entry60891

  • Like 3
Link to post
Share on other sites

Great job, Dipscom. I suspect you are right. immediateRender:false should do the trick. Thanks for all your help. I'll be back at headquarters this afternoon.

 

Barman,

 

Glad to hear you are using the modular technique from the seminar! As for using TimelineLite and Max you can mix and match. I sort of use Max out of habit only when I know I need to repeat or use other features.

 

If you need more help please create a simple demo. We don't need to see your production assets. Just a few simple animations of some divs should do the trick.

 

Thx!

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

×