GSAP 2.1 Released

February 18th 2019 | GreenSock


There are plenty of large and small updates in GSAP 2.1; here are a few highlights...

Advanced staggers

Advanced staggering makes it surprisingly simple to get rich, organic timing effects with very little code. Each tween's start time can be distributed according to any ease and/or based on how close each element is to a position in the list. For example, you can have things emanate outward from the "center" or a certain index. It'll even accommodate grids, complete with auto-calculated columns and rows (great for responsive layouts)! The interactive demo below explains it all visually (notice there's an embedded video explanation too):

See the Pen Advanced Staggers in GSAP by GreenSock (@GreenSock) on CodePen.

So setting up an advanced stagger is as simple as:

TweenMax.staggerTo(".yourClass", 2, {
        amount: 2, //total seconds to divide up among staggers
        from: "center", //or an index value. Determines where staggers originate
        grid:"auto", //or [columns, rows] 
        ease: Power1.easeIn //determines spacing

Parts of the advanced staggering features were prompted by suggestions from GSAP users inspired by Julian Garnier's API in anime, so we tip our hat to his efforts. He's a great contributor to the animation community.

MorphSVG type:"rotational"

There's an entirely new type of morph that leverages rotational and length data to move anchors and control points which can deliver cleaner, more intuitive morphs. Plus it completely eliminates kinks that can occasionally creep in with linear interpolation. The video below explains.

Watch the video

To tap into this new style of morphing, just set the type:"rotational""#shape1", 2, {

Or set it as the default to affect all morphs:

MorphSVGPlugin.defaultType = "rotational"; //default is "linear"

Demo 1: preventing kinks

Demo 2: more natural morphs

Fixing odd results by declaring a custom origin

The default origin is 50% 50% which usually works great, but sometimes the rotations around that point look odd, as shown below. In cases like this, it's best to experiment and set your own custom origin to improve things even more. We created a findMorphOrigin() utility function which is in the codepen below (and you can copy it into your own) which allows you to simply feed in a start and end shape and then it'll superimpose an origin that you can drag around and see exactly how it affects the morph! In the demo below, go into the JS panel and un-comment the findMorphIndex() line and you'll see exactly how this works. Drag the origin around and watch how it affects things.

See the Pen MorphSVG: fixing origin weirdness by GreenSock (@GreenSock) on CodePen.

Note: you must load Draggable for this to work.

So to set a custom origin, it would look like:"#shape1", 2, {
        origin:"20% 60%" //or to define a different origin for the start and end shapes, "20% 60%,45% 30%"

Is the new type:"rotational" a silver bullet for making every morph perfectly intuitive? No, but it's a great option that delivers more natural morphs in many cases.

MorphSVG canvas rendering

SVG is fantastic, but sometimes developers have a canvas-based project (often for rendering performance reasons). They haven't been able to leverage the intuitive morphing that MorphSVG provides in a highly-performant way...until now. The new MorphSVG plugin allows you to define a render function that'll be called every time the path updates, and it will receive two parameters:

  1. rawPath [array]: A RawPath is essentially an array containing an array for each contiguous segment with alternating x, y, x, y cubic bezier data. It's like an SVG <path> where there's one segment (array) for each "M" command; that segment (array) contains all of the cubic bezier coordinates in alternating x/y format (just like SVG path data) in raw numeric form which is nice because that way you don't have to parse a long string and convert things. For example, this SVG <path> has two separate segments because there are two "M" commands:
    <path d="M0,0 C10,20,15,30,5,18 M0,100 C50,120,80,110,100,100" />

    So the resulting RawPath would be:

      [0, 0, 10, 20, 15, 30, 5, 18],
      [0, 100, 50, 120, 80, 110, 100, 100]

    For simplicity, the example above only has one cubic bezier in each segment, but there could be an unlimited quantity inside each segment. No matter what path commands are in the original <path> data string (cubic, quadratic, arc, lines, whatever), the resulting RawPath will ALWAYS be cubic beziers.

  2. target [object]: the target of the tween (usually a <path>)

This means you can even render morphs to super high-performance engines like PixiJS or anything that'll allow you to draw cubic beziers!

Demo: MorphSVG canvas rendering

See the Pen MorphSVG canvas rendering by GreenSock (@GreenSock) on CodePen.

Here's an example of a tween and a render function that'd draw the morphing shape to canvas:

var canvas  = document.querySelector("canvas"),
	ctx = canvas.getContext("2d"),
	vw = canvas.width  = window.innerWidth,
	vh = canvas.height = window.innerHeight;

ctx.fillStyle = "#ccc";"#hippo", 2, {

function draw(rawPath, target) {  
  var l, segment, j, i;
  ctx.clearRect(0, 0, vw, vh);
  for (j = 0; j < rawPath.length; j++) {
    segment = rawPath[j];
    l = segment.length;
    ctx.moveTo(segment[0], segment[1]);
    for (i = 2; i < l; i+=6) {
      ctx.bezierCurveTo(segment[i], segment[i+1], segment[i+2], segment[i+3], segment[i+4], segment[i+5]);
    if (segment.closed) {

To set a default render method for all tweens:

MorphSVGPlugin.defaultRender = yourFunction; 

Got questions?

If you haven't checked out the forums, you're missing out! It's a great place to get your questions answered and participate in the community. We carefully monitor and answer questions there.


View the full changelog here (there's a lot).
Happy tweening!



Version: 2.1.2 updated 2019-03-01




        By using GreenSock code, you agree to the terms of use.

        For an all-access pass to premium content

        Join Club GreenSock