JavaScript tutorial: Animated charts with React-vis

With React-vis, breathing life into a chart is as simple as adding a single word to our code

JavaScript tutorial: Animated charts with React-vis
Thinkstock

The last two weeks we built up a few charts with Uber’s open-source library, React-vis, drawing on the City of New York’s Popular Baby Names data set. This week we’ll look at adding some animation to the charts to give users visual cues about changes in the data over time. By the end of this post, we’ll have a set of charts that can be filtered by ethnicity with animated transitions.

Before we get into any animations, we’ll first need to refactor the way we massage the CSV data into the format we expect for our charts. Currently, that all happens within the component constructor. Because we’ll need to call a lot of that same logic later when we want to filter values out, the first thing we’ll want to do is abstract the processing out to methods. We’ll still call those methods in the constructor, but we’ll also be able to call them when the filter changes without having to repeat the implementation.

We’ll also have to make some of our processing code a bit more dynamic. We’ve got some hard-coded values relating to the most popular baby names, but we’ll want to dynamically calculate those values based on a data set we pre-filter for ethnicity and pass in. In the spirit of wishful thinking, we can sketch out how we would ideally process the data:

  calculateChartData(data) {
    const totalBabiesByYear = this.getTotalBabiesByYear(data);
    const top10BabyNames = this.getTopBabyNames(data, 10);
    const namesWithData = this.getYearlyDataForNames(data, top10BabyNames);
    return {
      ethnicityFilter,
      totalBabiesByYear,
      namesWithData,
    };
  }

// We can then use this method in our constructor….
const newData = this.calculateChartData(data);
// … or later on when we want to filter
const newData = this.calculateChartData(data.filter((d) => d.ethnicity === someValue))

It doesn’t matter that these methods don’t yet exist—in fact, that’s the point. By imagining a clear way of interacting with data we can determine which abstractions need to be created. For example, we imagined a getTopBabyNames function that takes a set of data and a number and will return that number of the most popular names. This imaginary API guides our actual implementation. I won’t go through the refactoring and implementation step-by-step, but you can see all the code on GitHub.

Now that we know we can filter data and regenerate data in the shape our charts expect, we can start to think about how we go about animating the charts. Luckily, the React-vis library has a consistent API that lets us add a single property to any series to enable animated transitions: animation. We can add the animation property to each of our LineMarkSeries components and to our VerticalBarSeries component as well:

<LineMarkSeries
  animation
  onValueMouseOver={(d) => this.setState({hoverData: d})}
  key={name}
  data={data}
/>

// ...and

<VerticalBarSeries
  animation
  data={totalBabiesByYear}
/>

When the data we pass in changes, React-vis will automatically take care of the animations for us using the React-motion animation library. The animations can be enabled in their simplest form using the animation attribute as shown above, but two other uses are available as well, both of which customize the animation.

Instead of simply including the animation attribute, you can set it to a string value that is one of the following values: noWobble, gentle, wobbly, or stiff. These values act as presets for the animation; the best way to understand them is to see them in action. The React-vis documentation site has a live demo that demonstrates each of these presets.

The third way of enabling animations involves setting the animation attribute to an object with damping and stiffness properties and an optional nonAnimatedProps key. This method of enabling animations gives you direct access to React-motion and requires a deeper dive into understanding how changes in those values impact the animation.

react vis animation IDG

Simply adding the animation attribute provided most everything we needed for adding some action to our charts. There is some unexpected behavior when certain transitions in the data occur, which results in the effect of no animation at all. The underlying cause is that the data before and the data after the transition have no overlapping values, which means we can’t interpolate between them. This makes sense from a data perspective, but it looks strange from the user’s perspective.

Little issues here and there with React-vis are vastly overshadowed by the ease with which you can create interactive, animated charts. I’ve used the library on heavy-duty interactive dashboards in the past and I will likely reach for it again in the future. Do you know of any tricks or tips when using React-vis? Do you have a killer alternative? Continue the conversation on Twitter: @freethejazz

Copyright © 2019 IDG Communications, Inc.