Introduction to react-spring for data visualization


Web animations fall into two main categories: CSS and spring-based animations.

In this lesson, we’ll explore react-spring, a popular library for creating spring-based animations in React. Let’s see how to use it to bring our graph elements to life.

Wip
4 minutes read

Animating a Circle

Let’s start with something simple for this first lesson.

Our goal is to animate a circle moving smoothly from one position to another. Here’s what the final effect will look like:


Pretty cool, right? 🙃

To achieve this, we’ll use react-spring, the most popular JavaScript library for spring-based animations.


react-spring homepage. The most famous lib for javascript animation (28k stars on github)


Full code

react-spring is incredibly powerful, but it can be a bit tricky to grasp, and I personally find its documentation a little unclear. 😞

For now, the two key features we need are the useSpring hook and the animated component.

With these two tools, we can create a Circle component that accepts a position prop. Whenever a new position value is passed, the circle smoothly transitions to its new location.

Here’s how the Circle component looks:


import { animated, useSpring } from 'react-spring';

export const Circle = ({ position }) => {

  const springProps = useSpring({
    to: {
      position: position
    },
  });

  return (
    <animated.circle
      r={38}
      cy={50}
      cx={springProps.position}
    />
  );
};

        

Explanation

In this code, we’re creating a simple Circle component that renders one circle. The component takes a position property, which controls the circle’s X position.

Whenever this prop updates, the circle’s position will change, but it will happen smoothly!

Here’s a breakdown of what’s happening:

🚚 Import

Once installed with a classic npm install react-spring, we need to import:

  • useSpring: a hook that helps us create animated values.
  • animated:a special version of elements (like <circle>) that can be animated.

🌸 Using useSpring

  • The useSpring hook is used to define an animation. It accepts an object where we specify the properties to animate and how to animate them. In this case, we're animating the position.
  • We now have access to springProps.position. If the position changes from 0 to 100, springProps.position will smoothly transition through values like 1, 3, 10, 15, and so on, until it reaches 100. react-spring handles the calculation of these intermediate values for us!

🔗 Binding the Animation to the Circle

  • Instead of using a regular circle SVG element, we use animated.circle. React-spring provides its own animated version of all HTML and SVG elements!
  • Instead of passing position directly to the cx property, we pass springProps.position, which contains all the intermediate values, ensuring the circle moves smoothly.

A very basic animation using react and react-spring.

🔥 Spring Config

Spring animations follow physics laws to make the animation feel natural. There are three key properties you can control to adjust the feel of the animation: mass, friction, and tension.

You can customize these properties in the useSpring hook like this:


const springProps = useSpring({
  to: { position, color },
  config: {
    mass: 5,
    friction: 120,
    tension: 120,
  }
});
  

But honestly, I strongly advise using one of the presets provided by the library, as they offer great results right out of the box.

Check out the preset effects in the example below:

react-spring offers a few presets for the animation feel. Try them in this sandbox!

To use one of the presets, you can do something like this:


const springProps = useSpring({
  position: 100,
  config: config.default
});
  

Deriving Values

Animating a value directly using react-spring, like we did for the position property, is straightforward.

However, in data visualization, we often need to derive one value from another.

For example, suppose we want the size of the circle to be proportional to the X position. You might think that we could simply use the springProps.position value as a regular number, like this:


return (
  <animated.circle
    cx={springProps.position}
    cy={50}
    r={springProps.position / 10} // This will not work! 😱
  />
);
  

Instead, to achieve this, we need to use the to() method of the springProps.position property, like so:


return (
  <animated.circle
    cx={springProps.position}
    cy={50}
    r={springProps.position.to((pos) => pos / 10)}
  />
);
  

This is called interpolation in react-spring terminology. You can learn more about it in the full documentation here.

Let’s take a look at the result!

Smooth animation where circle size is derived from X position.

Animating Text

So far, we’ve only animated numerical values—like smoothly transitioning the position from 1 to 100.

But react-spring is much more powerful than that! It can animate almost anything, including text and colors!

In the example below, watch how the number evolves progressively:

40

Demo: react-spring can also animate text, colors and so much more!

Exercises