Shape morphism for data visualization


Shape morphism is the art of transitioning between 2 shapes as smoothly as possible. This post explores how it can be useful for data visualization and how it can be done using React, d3.js, react-spring and flubber.

This post is about shape morphism, which means animating the properties that define the actual shape of the elements.
As always when talking about animation, it is good to recall this citation by Josh Comeau:

Animation is like salt: too much of it spoils the dish

-Shape morphism for dataviz: some examples

Here is a list of nifty viz examples using shape morphism to transition between several viz types


-Shape morphism: why

In the field of data visualization shape morphism is mostly usefull to transition between 2 chart types. It is pretty hard to implement that kind of smooth transition so why should we even care?


  • Eye catching effect

  • Highlight the direct relationship between 2 charts. During the transition one can follow a specific item and understand it's the same.
  • Make sure that we're looking at the same dataset, but represented differently

-What are we trying to do

Sometimes in dataviz we want to transition between 2 chart types, let's say between a pie chart and a barplot. This is pretty hard since the shapes used for those 2 charts are very different: arc versus rectangle.


This is still possible thanks to a few libraries. This post suggests to use d3.js to build the start and end svg path, flubberto interpolate those path, react-spring for the animation and react for the rendering.


This is the kind of thing we're gonna learn to build:


-Shape morphism on the web: a review

I knew nothing about shape morphism 3 weeks ago. It took me a lot of effort to browse the web and find what the most appropriate tools are. To avoid you the hassle, here is a quick summary:


  • SMIL (Synchronized Multimedia Integration Language) is a feature introduced in firefox 4, allowing to follow a motion path. Basically it means you can use an animate element in your svg that will support shape morphism.
    Unfortunately, this feature is probably get deprecated soon. Furthermore, it supports transition only between shapes with the same number of nodes.
    DocCodePen.

  • pure CSS: Chrome has started to allow shape morphing through css. You can simply change the d attribute of a path in a css file and add sometransition to it. But chrome only and same number of nodes only.
    CodePen

  • greenSock MorphSvg plugin: a promising javascript library for shape morphism, widely cited on the internet. Supports shapes with different number of nodes. But it's not free and not open source.
    WebsiteCodePen

  • superformula is a mathematic formula that can be used to describe many complex shapes. Using 6 numbers as parameters, this formula can build many complex shapes. Interpolating between 2 shapes becomes easy: we just have to interpolate those numbers. Problem: it does not work with any shape and building a chart from this formula is thus impossible.
    Example

  • d3-interpolate is a d3 module that provides a variety of interpolation methods. It works for paths, even with different number of nodes. But when the shape 2 has more nodes than shape 1 it just adds some nodes to the end of the shape 1 path. This result in a bad visual effect.
    Doc

  • d3-interpolate-path is an open-source js library that adds an interpolator optimized for SVG path elements. It works very well for path including segments only, but from my experience less well for arcs.
    DocDemo

  • Vizzu is a library for animated data visualizations and data stories. It looks very promising for transition between chart types. But since it is a library, it means that customization is limited to the offered options.
    DocDemo

None of the item of this list suits my need. We need an open source library capable of interpolating any path, even with different number of nodes..

-Shape interpolation with flubber

flubber is an open source javascript library built by Noah Veltman. Unlike most of the shape morphism libraries it works very well to interpolate shapes that are completely different and don't have the same number of nodes.


Let's start by creating 2 svg shapes

const shape1 = "M10,140 L50,60 L90,140 Z"; // triangle
const shape2 = "M350,50 L400,83 L400,116 L350,150 L300,116 L300,83"; // polygon

It's very straightforward to interpolate a y between the 2 of them thanks to the interpolate() function offlubber. This function expects 2 arguments: the starting shape and the ending shape:

const interpolator = interpolate(shape1, shape2);

interpolate() returns a function. This function accepts only 1 argument: a value between 0 (start) and 1 (end). It will return the interpolated shape for this progress.

interpolator(0.2)
// M110,58L113.25,62.825L116.5,67.65L119.75,72.475L123,77.3L126.25,82.125L129.5,86.95L.......Z

Here is a visualization of the final result

step: 0.0

Switching from a triangle to a polygon using flubber for shape interpolation


Awesome video by the Flubber creator: link

-Animating the transition with react-spring

Now that we know how to build an interpolated shape between a starting and an ending point, let's animated this transition using react-spring.

The transition is now animated thanks to react-spring, a react library for spring animation.

-Pie chart to barplot transtion

I knew nothing about shape morphism 3 weeks ago. It took me a lot of effort to browse the web and find what the most appropriate tools are. To avoid you the hassle, here is a quick summary:

-Violin to boxplot transition

I knew nothing about shape morphism 3 weeks ago. It took me a lot of effort to browse the web and find what the most appropriate tools are. To avoid you the hassle, here is a quick summary:

How to smoothly transition between a boxplot and a violin plot. Math by d3.js, rendering using react, animation using react-spring and interpolation using flubber.


Part Of A Whole

Contact

👋 Hey, I'm Yan and I'm currently working on this project!

Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!

    Contact

    👋 Hey, I'm Yan and I'm currently working on this project!

    Feedback is welcome ❤️. You can fill an issue on Github, drop me a message on Twitter, or even send me an email pasting yan.holtz.data with gmail.com. You can also subscribe to the newsletter to know when I publish more content!