Animate SVGs in Framer with GSAP

Green Sock’s Animation Platform (GSAP) is the easiest and most powerful way to animate SVGs in Framer.

Andrew Cunliffe
Framer
8 min readJul 19, 2017

--

A Little Background

There are a few articles out there on working with SVGs in Framer, most focus on what SVGs are, their various attributes, and the multiple ways of getting them into Framer. The most in-depth article I’ve seen on animating SVGs is this one by Thomas Law. Thomas uses CSS animations to animate the SVGs in his project, which is fine and works, but there is an easier way to do it using Green Sock’s Animation Platform or “GSAP.” You can learn more about GSAP on their site, but in a nutshell it’s a collection of JavaScript files and plugins that make it easy to create web animations that are compatible with multiple browser types, including out of date ones.

I got interested in animating SVGs in Framer following at keynote by Melissa Cameron at a recent SF Framer Session. Melissa wrote a great article about the basics of using SVGs in Framer, which I highly suggest.

Grab my prototype here to follow along. If you don’t have Framer, be sure to download their 14 day free trial to follow along with this tutorial.

Getting Started

This first step towards animating an SVG is creating a Framer Project and making an artboard in the Design tab. I love MMA, and can’t wait for the upcoming McGregor vs Mayweather fight (and yes I know it’s boxing not MMA). Fun fact about me: after I got out of the U.S. Army I went to college and when it came time to pick a major, I initially picked accounting because my favorite fighter of all time, Chuck Liddell, has an accounting degree. I ended up switching to finance, but such is life. Time to get our Framer project set up.

First, create an artboard by typing “A” on your keyboard. You can select one of the preloaded devices to make an artboard. I chose the default iPhone 7 size and added some images I had previously edited in Sketch (I edited them in Sketch because Framer Design is currently lacking features like circular gradients). I targeted and named the artboard “fighterScreen,” which we’ll use to call the artboard in the FlowComponent.

Setup Flow Component

When dealing with complex images and SVGs, I find it best to enable the preloader with Framer.Extras.Preloader.enable() to ensure they are loaded in the DOM before rendering. But it’s important to note that you should probably wait until the end to do this, especially if you plan on folding any code. I created a FlowComponent that shows “fighterScreen” as the first screen. I almost always create a FlowComponent when starting a new project. It provides a degree of consistency and enables screen transitions to be easily employed if the prototype becomes more than one screen. Here’s how the code should look:

Framer.Extras.Preloader.enable()Utils.domComplete ->
flowParent = new FlowComponent
width: Screen.width
height: Screen.height
backgroundColor: "#171717"

fighterScreen.blur = 20
conorM.scale = 0.90
floydM.scale = 0.90

flowParent.showNext(fighterScreen)

Create The SVG

Since I had already created the initial screen in Sketch, I only needed to make the two SVGs that I would be animating. One is a loading circle, the other is a “boxing bell”. We’ll only be animating the circle with GSAP. I exported the bell and the circle as SVGs.

Cleanup The SVG In A Text Editor

Generally, running your exported SVGs through SVGOMG by Jake Archibald is a good idea to clean things up. I downloaded the cleaned up version and opened it in Sublime Text to make sure everything looked good for import into Framer.

The SVG code should be nice and concise like this:

<svg width="182" height="182" xmlns="http://www.w3.org/2000/svg">
<circle cx="90" cy="90" r="90" transform="translate(1 1)" stroke-width="2" stroke="#EAEAEA" fill="none"/>
</svg>

Copy And Paste The SVG Into Framer

In the text editor hit ⌘ + A to select all the SVG code, then ⌘ + C to copy it. In order to animate SVGs in Framer with GSAP, they need to be “inline” which means placing the SVG code within the Framer code. Create a new layer in Framer that will be a container for the SVG, add HTML to that layer with “layer.html = ” and use triple quotes so that nothing breaks up the SVG code. Paste the SVG code within the two sets of triple quotes.

 loadingCircle = new Layer
parent: homeOverlay
x: Align.center
y: Align.center
height: 182
width: 182
backgroundColor: "null"

loadingCircle.html = """
<svg width="182" height="182" xmlns="http://www.w3.org/2000/svg">
<circle cx="90" cy="90" r="90" transform="translate(1 1)" stroke-width="2" stroke="#EAEAEA" fill="none"/>
</svg>
"""

Add GSAP to the Framer Project

Now we need to add the GSAP files and plugins into our Framer project and include them in our index.html file to be able to animate the SVG. To do this, sign up for GSAP, download the files and create a folder in your Framer project’s directory (I named mine “js”). Then, copy over the minified versions of their files, minified plugins folder (you only need to copy over the “DrawSVGPlugin.min.js,” “CSSPlugin.min.js,” “MorphSVGPlugin.min.js,”and “AttrPlugin.min.js” files for this example), the minified “easing” folder, and the minified “utils” folder, then add the JS files to the “index.HTML” file in the project directory. Checkout the index.HTM file in my project for what files to include there. With these added, the GSAP is ready to go.

Your project directory should now look something like this:

Now this is important: the SVGs need to have a fill =“none,” and “IDs” or “classes” added to their “paths” (or whatever shapes are contained in the SVG, eg: <circle>, <rect>, <ellipse>, <polygon>, <polyline>, and <line>). In this example we are going to morph the circle and draw it. I changed “fill” to “=none” in the SVG code and gave the circle a class of “.loadingCircle.” Depending on what program you used to export, you may need to add color to the stroke. In this example I used stroke=“#EAEAEA.”

You can add the fill style and the IDs/classes in the text editor before copying into Framer, but I prefer to add them in Framer and then quickly copy the ID or class names into the GSAP code.

Here’s how the circle class applied to the SVG looks:

loadingCircle.html = """
<svg width="182" height="182" xmlns="http://www.w3.org/2000/svg">
<circle class="loadingCircle" cx="90" cy="90" r="90" transform="translate(1 1)" stroke-width="2" stroke="#EAEAEA" fill="none"/>
</svg>
"""

Let’s Trace the Circle

I created a function called “traceCircle,” which fires as soon as the whole project loads by calling “traceCircle()” near the bottom of the code.

Now, we get to the part you’ve been waiting for— let’s setup the GSAP animations! We are going to be using GSAP’s SVGMorph and TimelineMax constructor which is a “powerful sequencing tool that acts as a container for tweens and other timelines, making it simple to control them as a whole and precisely manage their timing.” GSAP’s docs are extensive and you can read more about TimelineMax there.

In order to draw the circle using GSAP, we need to “morph” it into a path. This is achieved by morphing the class we assigned to the circle in this way:

MorphSVGPlugin.convertToPath("circle");

To create the TimelineMax we set it as a variable, in this case “loadingCircleTrace.

loadingCircleTrace = new TimelineMax()
  1. There are a lot of parameters that can be set within the constructor, but we are just going to do a straightforward trace here, so I didn’t include any.
  2. With the “loadingCircleTrace” variable set, next we need to add the .from() method to the “loadingCircleTrace” variable. Within the .from() method we call the “.loadingCircle” class added to the circle, set the animation to run for 2 seconds, add an easing curve (GSAP has a great visualizer for using their curves), and add the drawSVG value. In this case it’s a straight trace so I set the value at 0%, meaning that the SVG will trace from 0–100%.
  3. Done, now the SVG should animate!

Here’s the full GSAP draw code:

traceCircle = () -> 
MorphSVGPlugin.convertToPath("circle");
loadingCircleTrace = new TimelineMax()
loadingCircleTrace.from('.loadingCircle', 2, {ease: Elastic.easeInOut.config(0.5, 2), drawSVG:"0%"})
traced = true

Further Animations

I also set up animations that load in some text from offscreen right by making the top part of the “bell” SVG “shake”. Retrace the circle down to zero, show the “fighterScreen,” and scale up the images of Conor and Floyd:

textLoad = () ->
selectAFighter.animate
x: Align.center
options:
curve: Spring(damping: 0.65)
shake = (times = 4) ->

i = 0

right = new Animation bellIconTop,
x: bellIconTop.x + 3
rotation: + 1
options:
curve: "bezier-curve"
time: 0.08

left = new Animation bellIconTop,
x: bellIconTop.x - 3
rotation: - 1
options:
curve: "bezier-curve"
time: 0.08

right.onAnimationEnd ->
if i < times
left.start()
i++
else
bellIconTop.animate
rotation: 0
x: 0
options:
time: 0.1

left.onAnimationEnd ->
if i < times
right.start()
i++
else
bellIconTop.animate
rotation: 0
x: 0
options:
time: 0.1

right.start()
...traceCircle()

Utils.delay 1.25, ->
loadBellIconParent.start()
loadBellIconParent.onAnimationEnd ->
shake()
Utils.delay 0.65, ->
textLoad()
loadingCircleTrace = new TimelineMax({paused:false, repeat:0, yoyo:false})
loadingCircleTrace.to('.loadingCircle', 2, {ease: Elastic.easeInOut.config(0.5, 2), drawSVG:"0%"})
traced = false
Utils.delay 2, ->
if traced == false
homeOverlay.animate
opacity: 0
options:
time: 0.3
fighterScreen.animate
blur: 0
conorM.animate
scale: 1
floydM.animate
scale: 1

Check It Out In GIF Form

I hope this helps you get started animating SVGs in GSAP. If you have any questions about the other stuff I’m doing here, or need help using GSAP in your prototypes, feel free to reach out to me on Twitter or comment below!

--

--