Little Earth Spatial Programming

Little Earth / Field Notes / Morphing Between SVG Shapes

Data Visualization

Morphing Between SVG Shapes

Smoothly animating from one SVG shape to another comes down to one rule: both paths need the same number of nodes.

From the archive

This post was originally published in May 2015 on my old "Mostly a GIS Guy" blog. It has been preserved here and lightly edited for the move to Field Notes.

In order to animate between two shapes in SVG you need an equal number of nodes. This is because the node coordinates are what get adjusted during a transition. If one shape has more than another you get some really weird behaviour.

One approach is to manually edit one of the paths so the number of nodes matches the other. But that is pretty time consuming. I opt for the lazy approach of stuffing it through a filter.

I wrote polymorph to make the calculation between two shapes. Essentially transposing the nodes from one shape onto the path of another.

Start with a complex shape

This is a little over-simplified… but you start with a complex shape with lots of nodes.

Then say you want to animate it into a simple circle like this.

Note the destination path contains arcs. Polymorph can handle any type of SVG path for the destination. The source, and more complex, path must always contain linear lines. See SVG Path for more details.

Transpose the nodes

Here are the two paths and the single call that maps one onto the other:

Input and destination paths
var inputShape = "m 14.108932,44.306697 33.663417,-22.772311 49.257499,-6.435654 4.702982,24.504988 -13.613886,30.693115 42.326796,10.14853 44.80204,-10.14853 8.91091,30.940645 -3.46535,31.18816 -28.46539,23.51489 L 99.752625,177.72274 87.128843,144.55437 97.277373,118.56423 75.000112,97.029549 30.44559,94.059247 44.059472,65.841383 14.108932,44.306697";

var destinationShape = "m 191.90169,310.3161 a 51.514591,51.514591 0 1 1 -103.029181,0 51.514591,51.514591 0 1 1 103.029181,0 z";

var newShape = polymorph.transpose(inputShape, destinationShape);

The nodes are obviously enlarged for the purposes of this post. But you end up with a shape that is almost identical to the destination shape. However, the node numbers match.

You can transpose nodes in any direction. However, it makes most sense to convert from high to equal or less complexity.

Animate between them

Now use one of the handy dandy SVG libraries, such as Snap, Velocity, or D3, to transform between the two. The following example uses D3 to transform from geographic boundaries (just SVG paths) into circles, and back again.

Live demo · Open on CodePen ↗

← All Field Notes