TimelineMax extends TimelineLite, offering exactly the same functionality plus useful (but non-essential) features like repeat, repeatDelay, yoyo, currentLabel(), addCallback(), removeCallback(), tweenTo(), tweenFromTo(), getLabelAfter(), getLabelBefore(), getActive() (and probably more in the future). It is the ultimate sequencing tool that acts like a container for tweens and other timelines, making it simple to control them as a whole and precisely manage their timing. Without TimelineMax, building complex sequences would be far more cumbersome because you'd need to use the delay
special property for every tween. Here is a basic example:
TweenMax.to(element, 1, {x:100}); TweenMax.to(element, 1, {y:50, delay:1}); TweenMax.to(element, 1, {opacity:0, delay:2});
The above code animates the element to a translateX of 100px, then a translateY of 50px and finally its "opacity" to 0 (notice the delay
in all but the first tween). But what if you wanted to increase the duration of the first tween to 1.5? You'd need to adjust every delay thereafter. And what if you want to pause()
the whole sequence or restart()
it or reverse()
it on-the-fly or repeat it twice? This becomes quite messy (or flat-out impossible), but TimelineMax makes it incredibly simple:
var tl = new TimelineMax({repeat:2, repeatDelay:1}); tl.to(element, 1, {x:100}); tl.to(element, 1, {y:50}); tl.to(element, 1, {opacity:0}); //then later, control the whole thing... tl.pause(); tl.resume(); tl.seek(1.5); tl.reverse(); ...
Or use chaining to make it even shorter:
var tl = new TimelineMax(); tl.to(element, 1, {x:100}).to(element, 1, {y:50}).to(element, 1, {opacity:0});
Now you can feel free to adjust any of the tweens without worrying about trickle-down changes to delays. Increase the duration of that first tween and everything automatically adjusts.
Here are some other benefits and features of TimelineMax:
- Things can overlap as much as you want. You have complete control over where tweens/timelines are placed using the position parameter. Most other animation tools can only do basic one-after-the-other sequencing but no overlaps.
- Add labels, callbacks, play(), stop(), seek(), restart(), and even reverse() smoothly anytime.
- Nest timelines within timelines as deeply as you want. This means you can modularize your code and make it far more efficient. Imagine building your app with common animateIn() and animateOut() methods that return a tween or timeline instance, then you can string things together like
myTimeline.add( myObject.animateIn() ).add( myObject.animateOut(), "+=4").add( myObject2.animateIn(), "-=0.5")...
- Speed up or slow down the entire timeline with its
timeScale()
method. You can even tween it to gradually speed up or slow down the animation smoothly. - Get or set the progress of the timeline using its
progress()
ortotalProgress()
methods. For example, to skip to the halfway point, setmyTimeline.progress(0.5);
- Tween the
time(), totalTime(), progress(),
ortotalProgress()
to fastforward/rewind the timeline. You could even attach a slider to one of these to give the user the ability to drag forward/backward through the timeline. - Add
onComplete, onStart, onUpdate, onRepeat
and/oronReverseComplete
callbacks using the constructor'svars
object likevar tl = new TimelineMax({onComplete:myFunction});
- Kill the tweens of a particular object inside the timeline with
kill(null, target)
or get the tweens of an object withgetTweensOf()
or get all the tweens/timelines in the timeline withgetChildren()
- Set the timeline to repeat any number of times or indefinitely. You can even set a delay between each repeat cycle and/or cause the repeat cycles to yoyo, appearing to reverse direction every other cycle.
- get the active tweens in the timeline with getActive().
- Get the
currentLabel()
or find labels at various positions in the timeline usinggetLabelAfter()
andgetLabelBefore()
- You can export all the tween/timelines from the root (master) timeline anytime into a TimelineLite instance using
TimelineLite.exportRoot()
so that you canpause()
them all orreverse()
or alter theirtimeScale
, etc. without affecting tweens/timelines that you create in the future. Imagine a game that has all its animation driven by the GreenSock Animation Platform and it needs to pause or slow down while a status screen pops up. Very easy.
Special Properties and Callbacks
You can optionally use the constructor's vars
parameter to configure a TimelineMax with a variety of options.
new TimelineMax({onComplete:myFunction, repeat:2, repeatDelay:1, yoyo:true});
All TimelineMax vars' properties are described below.
Sample code:
//create the timeline that repeats 3 times with 1 second between each repeat and then calls myFunction() when it completes var tl = new TimelineMax({repeat:3, repeatDelay:1, onComplete:myFunction}); //add a tween tl.add( TweenLite.to(element, 1, {x:200, y:100}) ); //add another tween 0.5 seconds after the end of the timeline (makes sequencing easy) tl.to(element, 0.5, {opacity:0}, "+=0.5"); //reverse anytime tl.reverse(); //Add a "spin" label 3-seconds into the timeline tl.addLabel("spin", 3); //insert a rotation tween at the "spin" label (you could also define the insertion point as the time instead of a label) tl.to(element, 2, {rotation:"+=360"}, "spin"); //go to the "spin" label and play the timeline from there tl.play("spin"); //nest another TimelineMax inside your timeline... var nested = new TimelineMax(); nested.to(element2, 1, {x:200}); tl.add(nested);
How do timelines work? What are the mechanics like?
Every animation (tween and timeline) is placed on a parent timeline (except the 2 root timelines - there's one for normal tweens and another for "useFrames" ones). In a sense, they all have their own playheads (that's what its "time" refers to, or "totalTime" which is identical except that it includes repeats and repeatDelays) but generally they're not independent because they're sitting on a timeline whose playhead moves. When the parent's playhead moves to a new position, it updates the childrens' too.
When a timeline renders at a particular time, it loops through its children and says "okay, you should render as if your playhead is at ____" and if that child is a timeline with children, it does the same to its children, right on down the line.
The only exception is when the tween/timeline is paused in which case its internal playhead acts like it's "locked". So in that case, it's possible (likely in fact) that the child's playhead wouldnot be synced with the parent's. When you unpause it (resume()
), it essentially picks it up and moves it so that its internal playhead is synchronized with wherever the parent's playhead is at that moment, thus things play perfectly smoothly. That is, unless the timeline's smoothChildTiming
is to false
in which case it won't move - its startTime
will remain locked to where it was.
So basically, when smoothChildTiming
is true
, the engine will rearrange things on the fly to ensure the playheads line up so that playback is seamless and smooth. The same thing happens when you reverse()
or alter the timeScale
, etc. But sometimes you might not want that behavior - you prefer to have tight control over exactly where your tweens line up in the timeline - that's when smoothChildTiming:false
is handy.
One more example: let's say you've got a 10-second tween that's just sitting on the root timeline and you're 2-seconds into the tween. Let's assume it started at exactly 0 on the root to make this easy, and then when it's at 2-seconds, you do tween.seek(5)
. The playhead of the root isn't affected - it keeps going exactly as it always did, but in order to make that tween jump to 5 seconds and play appropriately, the tween's startTime
gets changed to -3. That way, the tween's playhead and the root playhead are perfectly aligned.