Writing Smarter Animation Code

Avatar of Carl Schooff
Carl Schooff on

If you’ve ever coded an animation that’s longer than 10 seconds with dozens or even hundreds of choreographed elements, you know how challenging it can be to avoid the dreaded “wall of code”. Worse yet, editing an animation that was built by someone else (or even yourself 2 months ago) can be nightmarish.

In these videos, I’ll show you the techniques that the pros use keep their code clean, manageable, and easy to revise. Scripted animation provides you the opportunity to create animations that are incredibly dynamic and flexible. My goal is for you to have fun without getting bogged down by the process.

We’ll be using GSAP for all the animation. If you haven’t used it yet, you’ll quickly see why it’s so popular – the workflow benefits are substantial.

See the Pen SVG Wars: May the morph be with you. (Craig Roblewsky) on CodePen.

The demo above from Craig Roblewsky is a great example of the types of complex animations I want to help you build.

This article is intended for those who have a basic understanding of GSAP and want to approach their code in a smarter, more efficient way. However, even if you haven’t used GSAP, or prefer another animation tool, I think you’ll be intrigued by these solutions to some of the common problems that all animators face. Sit back, watch and enjoy!

Video 1: Overview of the techniques

The video below will give you a quick behind-the-scenes look at how Craig structured his code in the SVG Wars animation and the many benefits of these workflow strategies.

Although this is a detailed and complex animation, the code is surprisingly easy to work with. It’s written using the same approach that we at GreenSock use for any animation longer than a few seconds. The secret to this technique is two-fold:

  1. Break your animation into smaller timelines that get glued together in a master (parent) timeline.
  2. Use functions to create and return those smaller timelines.

This makes your code modular and easy to edit.

Video 2: Detailed Example

I’ll show you exactly how to build a sequence using functions that create and return timelines. You’ll see how packing everything into one big timeline (no modular nesting) results in the intimidating “Wall of Code”. I’ll then break the animation down into separate timelines and use a parameterized function that does all the heavy lifting with 60% less code!

Let’s review the key points…

Avoid the dreaded wall of code

A common strategy (especially for beginners) is to create one big timeline containing all of the animation code. Although a timeline offers tons of features that accommodate this style of coding, it’s just a basic reality of any programming endeavor that too much code in one place will become unwieldy.

Let’s upgrade the code so that we can apply the same techniques Craig used in the SVG wars animation…

See the Pen Wall of Code on CodePen.

Be sure to investigate the code in the “JS” tab. Even for something this simple, the code can be hard to scan and edit, especially for someone new to the project. Imagine if that timeline had 100 lines. Mentally parsing it all can be a chore.

Create a separate timeline for each panel

By separating the animation for each panel into its own timeline, the code becomes easier to read and edit.

var panel1 = new TimelineLite();
panel1.from(...);
  ...

var panel2 = new TimelineLite();
panel2.from(...);
  ...

var panel3 = new TimelineLite();
panel3.from(...);
  ...

Now it’s much easier to do a quick scan and find the code for panel2. However, when these timelines are created they will all play instantly, but we want them sequenced.

See the Pen

No problem – just nest them in a parent timeline in whatever order we want.

Nest each timeline using add()

One of the greatest features of GSAP’s timeline tools (TimelineLite / TimelineMax) is the ability to nest animations as deeply as you want (place timelines inside of other timelines).

The add() method allows you add any tween, timeline, label or callback anywhere in a timeline. By default, things are placed at the end of the timeline which is perfect for sequencing. In order to schedule these 3 timelines to run in succession we will add each of them to a master timeline like so:

//create a new parent timeline
var master = new TimelineMax();

//add child timelines
master.add(panel1)
  .add(panel2)
  .add(panel3);

Demo with all code for this stage:

See the Pen

The animation looks the same, but the code is much more refined and easy to parse mentally.
Some key benefits of nesting timelines are that you can:

  • Scan the code more easily.
  • Change the order of sections by just moving the add() code.
  • Change the speed of an individual timeline.
  • Make one section repeat multiple times.
  • Have precise control over the placement of each timeline using the position parameter (beyond the scope of this article).

Use functions to create and return timelines

The last step in optimizing this code is to create a function that generates the animations for each panel. Functions are inherently powerful in that they:

  • Can be called many times.
  • Can be parameterized in order to vary the animations they build.
  • Allow you to define local variables that won’t conflict with other code.

Since each panel is built using the same HTML structure and the same animation style, there is a lot of repetitive code that we can eliminate by using a function to create the timelines. Simply tell that function which panel to operate on and it will do the rest.

Our function takes in a single panel parameter that is used in the selector string for all the tweens in the timeline:

function createPanel(panel) {
  var tl = new TimelineLite();
  tl.from(panel + " .bg", 0.4, {scale:0, ease:Power1.easeInOut})
    .from(panel + " .bg", 0.3, {rotation:90, ease:Power1.easeInOut}, 0)
    .staggerFrom(panel + " .text span", 1.1, {y:-50, opacity:0, ease:Elastic.easeOut}, 0.06)
    .addLabel("out", "+=1")
      .staggerTo(panel + " .text span", 0.3, {opacity:0, y:50, ease:Power1.easeIn}, -0.06, "out")
    .to(panel + " .bg", 0.4, {scale:0, rotation:-90, ease:Power1.easeInOut});
  return tl; //very important that the timeline gets returned
}

We can then build a sequence out of all the timelines by placing each one in a parent timeline using add().

var master = new TimelineMax();
master.add(createPanel(".panel1"))
  .add(createPanel(".panel2"))
  .add(createPanel(".panel3"));

Completed demo with full code:

See the Pen

This animation was purposefully designed to be relatively simple and use one function that could do all the heavy lifting. Your real-world projects may have more variance but even if each child animation is unique, I still recommend using functions to create each section of your complex animations.

Check out this example in the wonderful pen from Sarah Drasner that’s built using functions that return timelines to illustrate how to do exactly that!

See the Pen

And of course the same technique is used on the main GSAP page animation:

See the Pen

GSDevTools

You may have noticed that fancy timeline controller used in some of the demos and the videos. GSDevTools was designed to super-charge your workflow by allowing you to quickly navigate and control any GSAP tween or timeline. To find out more about GSDevTools visit greensock.com/GSDevTools.

Conclusion

Next time you’ve got a moderately complex animation project, try these techniques and see how much more fun it is and how quickly you can experiment. Your coworkers will sing your praises when they need to edit one of your animations. Once you get the hang of modularizing your code and tapping into GSAP’s advanced capabilities, it’ll probably open up a whole new world of possibilities. Don’t forget to use functions to handle repetitive tasks.

As with all projects, you’ll probably have a client or art director ask:

  • “Can you slow the whole thing down a bit?”
  • “Can you take that 10-second part in the middle and move it to the end?”
  • “Can you speed up the end and make it loop a few times?”
  • “Can you jump to that part at the end so I can check the copy?”
  • “Can we add this new, stupid idea I just thought of in the middle?”

Previously, these requests would trigger a panic attack and put the entire project at risk, but now you can simply say “gimme 2 seconds…”

Additional Resources

To find out more about GSAP and what it can do, check out the following links:

CSS-Tricks readers can use the coupon code CSS-Tricks for 25% off a Club GreenSock membership which gets you a bunch of extras like MorphSVG and GSDevTools (referenced in this article). Valid through 11/14/2017.