Working with SVG Paths in Framer

Josh Puckett
Framer
Published in
5 min readNov 4, 2015

Scalable Vector Graphics (SVG) have been around for 14 years, but for many they’re still a mystery. This article and accompanying tools aims to demystify working with SVGs and to make it easy for anyone to render and animate beautiful SVG graphs, icons, or illustrations inside Framer Studio.

Let’s say we want to animate a simple line chart. We might export a graphic from Sketch, but then we’d have to mess with masks, which don’t play nicely with curves or more complex shapes, and we’d have a raster image that won’t scale to retina screens. Enter SVG paths. They’re vector by definition, and have rich stroke properties that we can use for animation. We’ll make the example on the left.

Getting SVGs into Framer Studio

Sketch fortunately has great support for SVGs, both in the app and as a part of their developer plugins. I made a simple plugin that will take any path and give you nicely formatted SVG data that we can then use in Framer. Just select a layer and run the plugin; the SVG info we need is copied to your clipboard.

That’s all you have to do in Sketch; now open up Framer Studio. I wrote an SVGLayer module that makes working with SVG’s as simple as copy and paste. Go ahead and import the module like so (making sure it’s in the ‘modules’ folder of your Framer project):

SVGLayer = require "SVGLayer"

The module extends the Layer class, so to create a new SVG layer, type:

path = new SVGLayer.create

Finally, paste the code that the Sketch plugin copied for you under that line, and voila! A working SVG layer in just 6 lines of code!

Animating SVG Paths

To animate the SVG Path you just created, simply call the animatePath() function:

path.animatePath()

By default, this will animate your curve from start to finish. You can pass in optional parameters (curve, time, and direction) like so:

path.animatePath
curve: “spring(45,15,0)”
direction: “backward”

That’s it!

Since this module extenders the Layer class, you can set all layer properties as you normally would. You can have as many SVG layers as you want, allowing you to make intricate animations like this:

Click below to grab the Framer module and Sketch plugin to get started with your own SVG paths!

Behind the scenes

First the bad parts: animating SVGs is still a little less than ideal; it’s essentially a hack. This method, while clever, relies on changing the perspective property of the layer. While this is very rarely used, there might be some cases where modifying that property on an SVG layer breaks the out of box behavior of this module. It also uses layer states to drive the animation.

How SVG paths work

SVG path elements have several stroke properties. These are what we manipulate to animate a path.

stroke //The color of the stroke
stroke-width //How thick the stroke is
stroke-linecap //Round, square, etc
stroke-dasharray //Dash length for the stroke
stroke-dashoffset //Offset for when the stroke begins

For any SVG layer, setting stroke-dasharray to the length of the path creates one dash that is, obviously, the length of path. If the stroke-dashoffset is 0, the dash begins at the start of the stroke and follows the path to the end.

If you set the offset to the length of the path, it’s effectively masked, and moved to just before the beginning of the path. Here’s an example where stroke-dashoffset is set to the path length - 20 pixels, which shows just the first 20 pixels of the stroke:

path.style[‘stroke-dashoffset’] = path.pathLength - 20

You can call layer.pathLength at any time to get the length of the SVG path.

Animation

So here’s the magic to animate the stroke, from the module.

@.on “change:perspective”, ->
if @direction == “forward”
dashOffset = Utils.modulate(@.perspective, [0, 1], [pathLength, 0])
@.style[‘stroke-dashoffset’] = dashOffset

In English: whenever the layer’s perspective property changes, if the direction is forward, map the value of perspective between 0 and 1 to the corresponding number between pathLength and 0, and then set the SVG ‘stroke-dashoffset’ of the layer’s path to that.

For example, of the pathLength was 100, and the perspective value was 0.5, then dashOffset would be 50.

By default all SVGLayers have perspective set to 0, and are created with a second state where perspective is 1. Utilizing layer states, and transitioning between them, allows us to get nice animation curves to manually drive the path’s stroke offset to create our animation.

--

--

Josh Puckett
Framer

Founding design partner @CombineVC. Led teams at @Wealthfront, @Dropbox, @Groupon. Aspiring amateur chef; eternally hopeful.