Animating with Lottie

Avatar of Idorenyin Udoh
Idorenyin Udoh on

I believe animation on the web is not only fun, but engaging in such a way that it has converted site visitors into customers. Think of the “Like” button on Twitter. When you “like” a tweet, tiny colorful bubbles spread around the heart button while it appears to morph into a circle around the button before settling into the final “liked” state, a red fill. It would be much less exciting if the heart just went from being outlined to filled. That excitement and satisfaction is a perfect example of how animation can be used to enhance user experience.

This article is going to introduce the concept of rendering Adobe After Effects animation on the web with Lottie, which can make advanced animations— like that Twitter button — achievable.

Bodymovin is a plugin for Adobe After Effects that exports animations as JSON, and Lottie is the library that renders them natively on mobile and on the web. It was created by Hernan Torrisi. If you’re thinking Oh, I don’t use After Effects, this article is probably not for me, hold on just a moment. I don’t use After Effects either, but I’ve used Lottie in a project.

You don’t have to use Lottie to do animation on the web, of course. An alternative is to design animations from scratch. But that can be time-consuming, especially for the complex types of animations that Lottie is good at. Another alternative is using GIF animations, which are limitless in the types of animation they can display, but are typically double the size of the JSON files that Bodymovin produces.

So let’s jump into it and see how it works.

Get the JSON

To use Lottie, we need a JSON file containing the animation from After Effects. Luckily for us, Icons8 has a lot of free animated icons here in JSON, GIF, and After Effects formats.

Add the script to HTML

We also need to get the Bodymovin player’s JavaScript library in our HTML, and call its loadAnimation() method. The fundamentals are demonstrated here:

<div id="icon-container"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.7.4/lottie.min.js">

<script>
  var animation = bodymovin.loadAnimation({
  // animationData: { /* ... */ },
  container: document.getElementById('icon-container'), // required
  path: 'data.json', // required
  renderer: 'svg', // required
  loop: true, // optional
  autoplay: true, // optional
  name: "Demo Animation", // optional
});
</script>

Activate the animation

After the animation has loaded in the container, we can configure it to how we want it to be activated and what action should activate it with event listeners. Her are the properties we have to work with:

  • container: the DOM element that the animation is loaded into
  • path: the relative path of the JSON file that contains the animation
  • renderer: the format of the animation, including SVG, canvas, and HTML
  • loop: boolean to specify whether or not the animation should loop
  • autoplay: boolean to specify whether or not the animation should play as soon as it’s loaded
  • name: animation name for future referencing

Note in the earlier example that the animationData property is commented out. It is mutually exclusive with the path property and is an object that contains the exported animated data.

Let’s try an example

I’d like to demonstrate how to use Lottie with this animated play/pause control icon from Icons8:

The Bodymovin player library is statically hosted here and can be dropped into the HTML that way, but it is also available as a package:

npm install lottie-web ### or yarn add lottie-web

And then, in your HTML file, include the script from the dist folder in the installed package. You could also import the library as a module from Skypack:

import lottieWeb from "https://cdn.skypack.dev/lottie-web";

For now, our pause button is in a loop and it also plays automatically:

Let’s change that so the animation is triggered by an action.

Animating on a trigger

If we turn autoplay off, we get a static pause icon because that was how it was exported from After Effects.

But, worry not! Lottie provides some methods that can be applied to animation instances. That said, the documentation of the npm package is more comprehensive.

We need to do a couple things here:

  • Make it show as the “play” state initially.
  • Animate it to the “paused” state on click
  • Animate between the two on subsequent clicks.

The goToAndStop(value, isFrame) method is appropriate here. When the animation has loaded in the container, this method sets the animation to go to the provided value, then stop there. In this situation, we’d have to find the animation value when it’s at play and set it. The second parameter specifies whether the value provided is based on time or frame. It’s a boolean type and the default is false (i.e., time-based value). Since we want to set the animation to the play frame, we set it to true.

A time-based value sets the animation to a particular point in the timeline. For example, the time value at the beginning of the animation, when it’s paused, is 1. However, a frame-based value sets the animation to a particular frame value. A frame, according to TechTerms, is an individual picture in a sequence of images. So, if I set the frame value of the animation to 5, the animation goes to the fifth frame in the animation (the “sequence of images” in this situation).

After trying different values, I found out the animation plays from frame values 11 through 16. Hence, I chose 14 to be on the safe side.

Now we have to set the animation to change to pause when the user clicks it, and play when the user clicks it again. Next, we need the playSegments(segments, forceFlag) method. The segments parameter is an array type containing two numbers. The first and second numbers represent the first and last frame that the method should read, respectively. The forceFlag is a boolean that indicates whether or not the method should be fired immediately. If set to false, it will wait until the animation plays to the value specified as the first frame in the segments array before it is triggered. If true, it plays the segments immediately.

Here, I created a flag to indicate when to play the segments from play to pause, and from pause to play. I also set the forceFlag boolean to true because I want an immediate transition.

So there we have it! We rendered an animation from After Effects to the browser! Thanks Lottie!

Canvas?

I prefer to use SVG as my renderer because it supports scaling and I think it renders the sharpest animations. Canvas doesn’t render quite as nicely, and also doesn’t support scaling. However, if you want to use an existing canvas to render an animation, there are some extra things you’d have to do.

Doing more

Animation instances also have events that can also be used to configure how the animation should act.

For example, in the Pen below, I added two event listeners to the animation and set some text to be displayed when the events are fired.

All the events are available on the npm package’s docs. With that I say, go forth and render some amazing animations!