Comparing JavaScript animation libraries
Tags: javascript, webdev
Published: 2020-05-14 16:32:43

---
title: Comparing JavaScript animation libraries
published: true
date: 2020-04-22 13:00:08 UTC
tags: javascript, webdev
canonical_url: https://blog.logrocket.com/comparing-javascript-animation-libraries/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/b4ukh8olbcjma4su8cd7.jpeg
---
**Written by [Andrew Evans](https://blog.logrocket.com/author/andrewevans/)**✏️

If you do any type of frontend web development today, animation is likely part of your daily work, or at least the project that you’re working on. Animation in JavaScript has come very far in recent years, from animating text or an image to full-fledged 3D animation with tools like [WebGL](https://get.webgl.org/).

There are a lot of JavaScript frameworks that provide animation functionality. There are also several libraries that work with the canvas and WebGL to create interactive experiences.

In this post, I’m going to do a comparison of four different JavaScript animation libraries. The libraries I’m listing here are by no means the only options, but hopefully, they’ll show you patterns that you can follow when adding any animation to your projects.

For this post, we’ll look at the following:

- [Anime.js](https://animejs.com/)
- [p5.js](https://p5js.org/)
- [Three.js](https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene)
- [Green Sock Animation Platform (GSAP)](https://greensock.com/get-started/)

I’ll cover implementations with a [React](https://reactjs.org/) project, but you should be able to follow similar patterns for any frontend framework (or vanilla JavaScript as well). You can view the project I built [here](https://github.com/andrewevans0102/compare-javascript-animation-libraries). I’ve also built components for examples with each of the libraries, which you can be see [here](https://github.com/andrewevans0102/compare-javascript-animation-libraries/tree/master/src/components).

In the next sections, I’ll discuss how to use each of the above libraries. I’m going to cover basics and their implementation in a [React](https://reactjs.org/) project. I’ll also offer some pros and cons that I found when working with them.

This post assumes some familiarity with React and JavaScript projects. All the libraries I discuss can be applied to any JavaScript framework, it’s just a matter of correctly importing the library and calling the APIs discussed.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## Anime.js

[Anime.js](https://animejs.com/) provides a basic API that lets you animate almost anything you can think of. With Anime.js, you can do basic animations where you move objects back and forth, or you can do more advanced animations where you restyle a component with an action.

Anime.js also offers support for things like timelines, where you can create an animated sequence of events. This is particularly useful when it comes to presenting several events at once.

To use Anime.js, you first have to install it through either npm install or download it directly from [the GitHub project here](https://github.com/juliangarnier/anime).

Since the example project is based on React, I’m using npm:

```jsx
npm install animejs --save
```

Once you’ve got it installed, you can import it into your component with standard JavaScript imports:

```jsx
import anime from "animejs";
```

Once imported, you can define animations with the `anime` object:

```jsx
    anime({
      targets: ".anime__label",
      translateX: "250px",
      rotate: "1turn",
      backgroundColor: "#FFC0CB",
      duration: 800,
      direction: "alternate"
    });
```

Anime.js always requires a “target,” as you see here. Targets can include anything that you use to identify DOM elements. In this case, I’ve identified elements that contain the `.container__label` class.

Beyond defining your target, you also typically define CSS properties — in this case, I’ve defined a `backgroundColor`.

You also define “Property Parameters” and “Animation Parameters,” as I have done in this example with:

- `translateX`
- `rotate`
- `duration`
- `direction`
- And others

So if you define the animation like I have above, you are saying the following:

1. Animate `.container__label` class elements to move to the right 250px
2. Rotate once
3. Apply the background color of `#FFC0CB`
4. Perform the animation for a duration of 800ms
5. Complete the animation and then repeat (`direction:` `"``alternate``"`)

Putting it all together, it should look like this:

{% youtube hJ7SekzMvzg %}

Now if you want to animate multiple objects, you can connect the animations together with a timeline. The process for this is just to define a timeline, and then add additional animations like the following (this example was copied from the Anime.js docs):

```jsx
    const tl = anime.timeline({
      easing: 'easeOutExpo',
      duration: 800,
      direction: "alternate"
    });
    tl
    .add({
      targets: '.anime__timeline--pink',
      translateX: 250,
    })
    .add({
      targets: '.anime__timeline--blue',
      translateX: 250,
    })
    .add({
      targets: '.anime__timeline--yellow',
      translateX: 250,
    });
```

So what this does is define an initial animation event that uses easing (movement behavior) that lasts for 800ms and alternates just like the text animation.

Then, with the `.add` methods, we add additional animations specific to elements that have the `.anime __timeline--pink`, `.anime__ timeline--blue`, and `.anime__timeline--yellow` classes.

The resulting behavior looks like the following:

{% youtube LcXEL30r5Ks %}

For a complete copy of the code for these elements, please look at the `animejs` component [here](https://github.com/andrewevans0102/compare-javascript-animation-libraries/blob/master/src/components/Anime.js).

These two examples just scratch the surface of what Anime.js can do for your projects. There are multiple examples [in their docs here](https://animejs.com/documentation/). Additionally, there are a lot of great examples available on [codepen here.](https://codepen.io/collection/XLebem)

**Pros** :

- Super easy to set up
- Fairly intuitive
- Lots of good examples
- Compatible with modern browsers

**Cons** :

- Documentation is a little too sparse at times
- The information on CSS properties is not super easy to understand
- [Easing](https://animejs.com/documentation/#linearEasing) is cool, but the custom patterns took a second to read
- Using selectors was good, but required a coordinated effort between styling and animation definitions

Ultimately, I really liked Anime.js, except that I would definitely recommend adding more documentation. Also, since the animations required selectors, it made it a little difficult at times to translate elements styling to what I wanted animated.

## p5.js

The [p5.js](https://p5js.org/) library is an interpretation of the original [Processing project](https://processing.org/) started by [Casey Reas](https://en.wikipedia.org/wiki/Casey_Reas) and [Ben Fry](https://en.wikipedia.org/wiki/Ben_Fry) at MIT. Processing included an editor and language that attempted to make visual designs easier for artists and creators.

The original project was supported in multiple languages, and made creating visual elements much easier than other basic libraries like Java’s Swing, for example. p5.js brings these concepts to JavaScript and enables you to quickly build out animations with the HTML canvas. p5.js also lets you create 3D images and audio.

To get started, you can either directly download the p5.js library or install it with npm:

```jsx
npm i p5
```

Wherever you want to use p5.js, you create animations as a “sketch” object.

The `setup` method enables you to initiate your canvas object and apply any sizing, etc. The `draw` method lets you apply any recurring behavior to the page as your canvas refreshes.

If you look to the [Get Started](https://p5js.org/get-started/) page for p5.js, they define a simple example (with an animation) as the following:

```jsx
function setup() {
  createCanvas(640, 480);
}

function draw() {
  if (mouseIsPressed) {
    fill("#000000");
  } else {
    fill("#FFFFFF");
  }
  ellipse(mouseX, mouseY, 80, 80);
}
```

In `setup` above, the call to `createCanvas` creates a canvas that is 640x480px.

Then, the `draw` method adds an event listener for the `mouseIsPressed` event to apply a `fill` property based on whether the mouse is clicked. This `fill` property is basically applying the color specified in the parentheses (in our case, it’s black when pressed and white when not pressed).

Then, the `ellipse` method is called to draw an ellipse on the screen. Since this method is called whenever the canvas pages or refreshes, it creates an animation effect of drawing circles on the screen.

Since in our example application we are using React, this is a little different. In React, we just have to reference the p5 library and then append a sketch to the DOM that is returned, as you can see here:

```jsx
import React, { Component } from "react";
import "./../styles/_title.scss";
import p5 from 'p5';
class P5WithSketch extends Component {
  constructor(props) {
    super(props)
    this.myRef = React.createRef()
  }

  Sketch = (p) => {
    let x = 100;
    let y = 100;
    p.setup = () => {
      p.createCanvas(640, 480);
    }
    p.draw = () => {
      if (p.mouseIsPressed) {
        p.fill("#000000");
      } else {
        p.fill("#FFFFFF");
      }
      p.ellipse(p.mouseX, p.mouseY, 80, 80);
    }
 }
  componentDidMount() {
    this.myP5 = new p5(this.Sketch, this.myRef.current);
  }
  render() {
    return (
      <div>
        <section className="title">
          <a
            className="title__heading"
            href="https://p5js.org/"
          >
            P5.js
          </a>
        </section>
        <section ref={this.myRef}>
        </section>
      </div>
    );
  }
}
export default P5WithSketch;
```

The final animation that is created looks like the following:

{% youtube gTz_5GQJDBQ %}

This is just the start of what you could do with p5.js. You can easily extend the basic animation here to react to user input as well as render full 3D elements. There are a lot of really great examples of p5.js sketches that showcase this behavior. Check out [their example page here for more info](https://p5js.org/examples/).

The full working component in my sample project can be found [here](https://github.com/andrewevans0102/compare-javascript-animation-libraries/blob/master/src/components/p5WithSketch.js).

**Pros** :

- Ability to scope animation and behavior to the initial setup and refresh of canvas elements
- Good documentation with lots of examples

**Cons** :

- Difficulty in having to create “sketch” objects to actually perform animations and behavior
- Connection between DOM elements and rendered canvas requires custom references

## Green Sock Animation Platform (GSAP)

The [Green Sock Animation Platform (GSAP)](https://greensock.com/) provides a fairly robust library that has animations for almost any type of effect your project could need. Additionally, they have really strong documentation that includes examples of how to interact with their APIs.

To get started with GSAP, you first just need to install it as a dependency to your project:

```jsx
npm i gsap
```

Once you’ve loaded it into your project, then it’s just a matter of defining animation behavior with the `gsap` object, like you see here:

```jsx
  animateText = () => {
    gsap.to(".gsap__label", { duration: 3, rotation: 360, scale: 0.5 });
  };
  animateSquare = () => {
    gsap.to(".gsap__square", { duration: 2, x: 200, ease: "bounce" });
  };
```

When working with GSAP, you’ll often notice the docs refer to animations as “tweens,” which is similar to the way we saw p5.js refer to animations as “sketches.”

When using GSAP, you use `to` and `from` methods to indicate start and stop behaviors. In the case of the two examples I’ve put here, they are applying animations to elements that have the `.container __label` and `.container__ square` style.

Similar to the way we worked with Anime.js, GSAP offers properties like `duration`, `rotation`, `ease`, and `scale`.

When applied to a template, the above example looks like the following:

{% youtube xGgUDxj3FQo %}

Similar to Anime.js, there are a lot of cool things you can do with GSAP. You can also do timelines and other sequenced animations. For a more in-depth walkthrough, check out the [Getting Started with GSAP page](https://greensock.com/get-started/). For a full list of examples, you can check out the [GSAP CodePen page](https://codepen.io/GreenSock).

A full working copy of the component that I’ve covered is in my sample project [here](https://github.com/andrewevans0102/compare-javascript-animation-libraries/blob/master/src/components/GSAP.js).

**Pros** :

- Very robust APIs with lots of possible animations
- Very good documentation with examples

**Cons** :

- Specific applications might have special cases. I didn’t really cover this, but GSAP also includes instructions around Angular, React, etc.
- Large amount of API options can be daunting to beginners

## Three.js

Up until this point, all of the animations have either interacted directly with DOM elements or added custom elements. The [Three.js](https://threejs.org/) library uses [WebGL](https://get.webgl.org/) to render animations.

What is WebGL? WebGL is a DOM API that enables you to render graphics in the browser. It does use the canvas element, but rather than generating a canvas and writing on top of it, as we saw with p5.js, WebGL allows you to call APIs to do the rendering for you.

Three.js is a library that orchestrates the WebGL calls in order to render images and graphics within the browser. This is really great if you want to create an animation or 3D graphic associated with your project.

Three.js has a great walkthrough sample project [that can be reached here](https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene). As I mentioned, my sample project is using React, so the setup is slightly different. The core concepts and API calls are all the same.

If you have any issues with understanding (or getting the example to work), I recommend reviewing the explanation [in the Three.js documentation here](https://threejs.org/docs/#manual/en/introduction/Creating-a-scene).

To get this working is a multistep process. We must first define the renderer to use for our animation:

```jsx
    const scene = new THREE.Scene();
    let camera = new THREE.PerspectiveCamera(75, 400 / 400, 0.1, 1000);
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(400, 400);
    this.mount.appendChild(renderer.domElement);
```

Three.js calls this “creating a scene.” The long and short of it is basically creating the area for the animation to occur.

Next we define objects we want to animate:

```jsx
    const geometry = new THREE.BoxGeometry(1, 1, 1);
    const material = new THREE.MeshNormalMaterial();
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
```

Here, we’re using Three.js global objects to define the cube and material associated with it for animation.

Next, we define the animation method:

```jsx
    camera.position.z = 5;
    const animate = function () {
      requestAnimationFrame(animate);
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;
      renderer.render(scene, camera);
    };
```

This is what will be called, and how Three.js calls the WebGL API methods to show the animation.

Finally, we call the `animate` method directly to render the animation:

```jsx
    animate();
```

To get all this working with React, we just put it in the `componentDidMount` lifecycle method of the component we want to show:

```jsx
  componentDidMount() {
    // create the scene and renderer for the animation
    const scene = new THREE.Scene();
    let camera = new THREE.PerspectiveCamera(75, 400 / 400, 0.1, 1000);
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(400, 400);
    this.mount.appendChild(renderer.domElement);

    // create the elements that become a rotating cube and add them to the scene
    const geometry = new THREE.BoxGeometry(1, 1, 1);
    const material = new THREE.MeshNormalMaterial();
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    // create the actual animation function that will draw the animation with WebGL
    camera.position.z = 5;
    const animate = function () {
      requestAnimationFrame(animate);
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;
      renderer.render(scene, camera);
    };
    // call the animation function to show the rotating cube on the page
    animate();
  }
```

The resulting animation looks like the following:

{% youtube SKvuFvrdYTc %}

There are a lot of cool things you can do with Three.js. I recommend checking out their [docs here](https://threejs.org/docs/index.html#manual/en/introduction/Creating-a-scene) and [examples here](https://threejs.org/examples/#webgl_animation_cloth).

A full working copy of the component I’ve covered is available in my sample project [here](https://github.com/andrewevans0102/compare-javascript-animation-libraries/blob/master/src/components/Three.js).

**Pros** :

- You get to leverage an API for interacting with WebGL, making it easier to work with the APIs
- You can leverage Three.js for creating graphics

**Cons** :

- It requires manually appending an element to the DOM
- There is a learning curve associated with the library and WebGL concepts

## Closing thoughts

I hope this post gave you a basic look at some different JavaScript animation libraries that are available today.

I wanted to note some commonalities between the four libraries I covered.

With Anime.js and GSAP, they both accomplished animations by importing a global object, identifying elements to apply animations to, and then defining the animation, like so:

```jsx
// anime.js
    anime({
      targets: ".anime__label",
      translateX: "250px",
      rotate: "1turn",
      backgroundColor: "#FFC0CB",
      duration: 800,
      direction: "alternate"
    });

// GSAP
gsap.to(".gsap__label", { duration: 3, rotation: 360, scale: 0.5 });
```

With p5.js and Three.js, custom elements were created and appended to the DOM. Both leveraged an HTML canvas to generate the associated animation, like so:

```jsx
// P5.js
Sketch = (p) => {
  let x = 100;
  let y = 100;
  p.setup = () => {
    p.createCanvas(640, 480);
  }
  p.draw = () => {
    if (p.mouseIsPressed) {
      p.fill("#000000");
    } else {
      p.fill("#FFFFFF");
    }
    p.ellipse(p.mouseX, p.mouseY, 80, 80);
  }
}

// Three.js
const scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(75, 400 / 400, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(400, 400);
this.mount.appendChild(renderer.domElement);
```

Seeing these common behaviors gives you an idea of what you could expect with any JavaScript animation library. As I stated in the intro, while this post covered these four libraries specifically, there are still many others that are available to you today.

The best part is that with the advances in both web development and browser technologies, JavaScript animations can do much more than ever before. I encourage you to review the documentation associated with the libraries covered here for more info.

Thanks for reading my post! Follow me on Twitter at [@AndrewEvans0102](https://twitter.com/AndrewEvans0102)!

* * * 
## Plug: [LogRocket](https://logrocket.com/signup/), a DVR for web apps
 
![LogRocket Dashboard Free Trial Banner](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png?resize=1200%2C677&ssl=1)
 
[LogRocket](https://logrocket.com/signup/) is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
 
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.
 
[Try it for free](https://logrocket.com/signup/).
* * *

The post [Comparing JavaScript animation libraries](https://blog.logrocket.com/comparing-javascript-animation-libraries/) appeared first on [LogRocket Blog](https://blog.logrocket.com).