
In the olden days of animation tweening was a term used to describe a frame by frame sequence, or what’s sometimes referred to as “in-betweens.” It’s that place where a single movement leads into the next to create one fluid motion. For those that have gray hair you may recall Flash; an application that used this term when referring to frame movements. Let’s take an insightful look into a few examples and give this tweening thing a good ol’ fashioned college try.
Tweening With TweenMax
For both examples in this tutorial I’ll be loading TweenMax.min.js which will give us access to TimelineMax and all the other amazing core tools GSAP has to offer. If you think back to our TimelineMax primer I discussed loading TweenMax.min.js as it’s more convenient, plus this one file contains pretty much all that we’ll need (also what’s recommended by GreenSock 99% of the time).
TweenMax extends TweenLite, adding many useful (but non-essential) features like repeat()
, repeatDelay()
, yoyo()
, updateTo()
, and more. TweenMax was built for convenience, providing a single JavaScript file containing everything you’ll commonly need for animating DOM elements. It essentially allows authors to specify single movements whereas TimelineMax will accept chained methods to create a more complex set of tweens/sequences.
Loader Sequence
Loaders are those objects given to users when they’re waiting for a process to load. They give us the power to explore tiny, micro-sized elements that can have complex or even simplistic interactions–plus they’re a blast to make.
Take a quick look at this “String of Pearls” demo:
Let’s break the sequence down for a better understanding into how this whole “tweening” thing works.
In order to create this sequence it will require use of the staggerTo method. If you don’t recall what a method is then I encourage you to stop right this minute and read my tutorial on mechanics.
According to GreenSock’s documentation, the staggerTo()
method:
“tweens an array of targets to a common set of destination values.
In our case those multiple targets will be each of the circles within the entire SVG.
- Our first argument for
staggerTo
will accept the selector we’re using for the circles (in this casecircles
). - The second argument will be our duration (how long the animation will last).
- The third argument is an object literal containing the properties we desire to tween.
- And the last argument will hold our stagger value (the amount of time between the start of each animation).
This would result in the following; assuming circles
contains three objects…
timeline.staggerTo(circles, 15, {x:0}, 0.2) // circle 1 starts at time 0 // circle 2 starts at time 0.2 // circle 3 starts at time 0.4
Loader Setup
To start off right, we’ll need to define a new timeline and a few settings for our configuration.
var loader = new TimelineMax({ repeat: -1, yoyo: true }), circles = $('svg circle'), stagger_options = { opacity: 0, y: -800, ease: Elastic.easeInOut };
To make this timeline repeat in the reverse direction I’m using the yoyo
key and setting its value to true
. Again, this will cause our sequence to play in the opposite direction once the animation reaches its ending frame. Triggering the animation will require targeting each circle inside the SVG and exactly why we’ll need a reference using the power of jQuery.
There are a number of ways noted by the docs to pass selectors (feel free to read more about that here). For this example I’ll select all the circles at once using jQuery’s typical selector syntax. It’s also a bit faster to store our reference in a variable for reuse later on, hence circles = $('svg circle')
.
The stagger_options
variable is an object literal which contains the properties to give this animation its life. We move our objects using the y
key because the GSAP CSSPlugin intelligently converts transform
values to matrix
equivalents and ultimately speeds things up for us. There are a whole list of transform short-hand properties that are far superior and much easier to use versus typical CSS transforms:
GSAP equivalent to CSS properties
CSS | GSAP |
---|---|
translateX() |
x |
translateY() |
y |
translateZ() |
z |
rotate() |
rotation |
rotateY() |
rotationY |
rotateX() |
rotationX |
scaleX() |
scaleX |
scaleY() |
scaleY |
skewX() |
skewX |
skewY() |
skewY |
We can also control the easing (the feel of the animation) and pass in various motion types. For the visual lovers out there you can checkout the ease visualizer by GreenSock to gain a better understanding into the myriad of eases available.

The final piece to this creation is attaching the staggerTo
method to our timeline and inserting the variables defined earlier and in the correct order for this particular method (elements, duration, options, stagger amount).
loader.staggerTo(circles, 0.875, stagger_options, 0.025);
Chaining a Second Tween
If you hunger to create another sequence once the stagger sequence is complete you could certainly chain another method such as fromTo
like so:
loader.staggerTo(circles, 0.875, stagger_options, 0.025) .fromTo(target: Object, duration: Number, fromVars:{}, toVars: {});
Taking it Further
Let’s give this a try with an SVG I call “Polyman.” Recently I wrote an article for CSS-Tricks on animating polygons and decided to use that similar example for another tweening exercise here. Let’s try using the staggerFromTo()
method and see what kind of magic we can conjure up.
The following SVG output (the XML) is slightly abbreviated for the sake of discussion, but as you’ll see our SVG comprises a few tags; specifically <g>
and <path>
. Also note the paths correlating to the man’s face are grouped together as sections in order to have finer control over the stagger (e.g. ears, eyes, nose…).
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 800 800" class="polyman"> <g id="ears"> <path fill="#E6BBBE" d="M346.5,344.2l-2.8-3.4l4.1-18.5L346.5,344.2z"></path> <path fill="#EAD9DD" d="M344,332.5l-0.3,8.3l4.1-18.5L344,332.5z"></path> <path fill="#EEDFE3" d="M346,307.1l1.8,15.2l0.4-22.1L346,307.1z"></path> </g> <!-- and so on --> </svg>
For the initial timeline setup we’ll define our global options using an object literal that will delay the initial animation, repeat the sequence, delay the animation on repeat and finally play the animation in reverse.
var tmax_options = { delay: 0.25, repeat: -1, repeatDelay: 0.25, yoyo: true };
Forcing Transform Values
Next up is a rather new and undocumented property that forces transform values to be placed in the SVG transform attribute (as opposed to a CSS style).
CSSPlugin.useSVGTransformAttr = true;
This
property was added in order to make things easier for developers to get around a bug in Safari
where combining opacity
and transforms
(such as transform: scale()
for example) would produce an odd result. As of 1.16.0 useSVGTransformAttr
is set to true
automatically and specifically targeted at our pal Safari so it’s no longer required for authors to define as I have above.
Since the staggerFromTo
method accepts separate arguments for from
and to
positions I like to setup both object literals outside the method for organizational and readability purposes.
var stagger_opts_from = { opacity: 0, scale: 0, transformOrigin: 'center center' }; var stagger_opts_to = { opacity: 1, scale: 1, ease: Elastic.easeInOut, force3D: true };
We define two object literals because we need all our from
and to
properties defined in order for this animation to do its thing. If it isn't clear we're going from the values defined in our stagger_opts_from
and ending with the values set within stagger_opts_to
.
The force3D
key forces GSAP to apply a 3D value to the element’s transform; meaning matrix3d()
instead of matrix()
, or translate3d()
instead of translate()
. This typically results in the browser putting the targeted element onto its own compositor layer allowing for more efficient updates with animations.
By default force3D
is set to auto
(as of 1.15.0) so there’s actually no need to use it at all (unless you specifically want the behavior of true
instead of auto
for that tween).
// layerizes the targets at the start of the tween and // keeps them that way using a 3D matrix where applicable // (for 2d and 3d transforms). force3D:true // layerizes the targets at the beginning of the tween and // also de-layerizes them (switching back to a 2D matrix or // transforms) at the end of the tween too. This prevents you // from creating and hanging onto hundreds of layered elements // (which can degrade performance) and also makes sure text // that may have been rasterized during the tween returns to // being sharp. force3D:auto
You can set the global force3D
value for all tweens using the defaultForce3D
property provided by CSSPlugin:
// also accepts 'false' or 'auto' CSSPlugin.defaultForce3D = true;
Or you could set this on a per-tween basis instead:
// will keep element layered after tween is complete timeline.to(element, 1, {x:300, force3D:true); // will keep element layered after tween is complete timeline.to(element, 1, {x:300, force3D:false);
Hide on Window Load
If your animation is attempting to override CSS properties you need to make sure that your particular specificity isn’t colliding with what’s declared in your JavaScript otherwise the native CSS values will take precedence and your animation will not react as expected.
/* Required Polyman Styles */ .polyman path { opacity: 0; }
The CSS above will hide Polyman on initial window load so we don’t initially see our bearded fellow much like you would experience with what’s commonly referred to as FOUT (Flash Of Unstyled Text).
Since the majority of our configuration is defined we can finally begin setting up our timeline, targeting the SVG paths, defining a stagger value (stagger_val
) and finishing by defining how long the entire animation will last (duration
).
var tl = new TimelineMax(tmax_options), path = $('svg.polyman path'), stagger_val = 0.0125, duration = 1.25;
Just like that and with the delicate wave of our magic wand and a slight sprinkle of unicorn dust we pass all the required variables that were defined as arguments into the staggerFromTo
method!
tl.staggerFromTo(path, duration, stagger_opts_from, stagger_opts_to, stagger_val, 0);
Viola! In one simple line the Polyman starts to breathe and become a real living thing (well not really). Pretty cool huh?
Next Time
In the next tutorial of our TweenMax series we’ll look at how to create a pause point on the timeline, so the animation automatically pauses when it reaches the desired point. The addPause() method is relatively new and allows you to place a pause anywhere in a timeline. It’s much more accurate than using a callback which calls a function to pause the function (which is what you had to do prior to addPause()
existing). Until next time happy tweening!
A special thanks to those readers following along on this GreenSock journey!
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post