Animation

How To Draw a Signature (with React and Framer Motion)

August 6, 2022

·

6 min read

–––

I believe small details can go a long way in improving a project - including this website! You may have noticed the subtle (or not so subtle) signature animation on the navigation bar and the footer.

If you want to build your own animated signature component for your website, here's how.

The Tools 🛠️

  • SVGs (Scalable Vector Graphics)
  • React (My front-end framework of choice)
  • Framer Motion (A React animation library)

1. Vectorize the Signature.

We want the signature in a vector image format so we can animate it as if it was drawn.

Vector 🖋️ graphics use math to render images. Raster 👾 graphics use a set of pixels to render images.

Essentially, vector images are composed of paths rather than pixels. This makes vector images scalable, lightweight, and easy to manipulate. Easy to manipulate means easy to animate.

Vector vs Raster

Let's run through the vectorizing process:

  1. Draw your signature on paper.
  2. Scan or take a picture of your signature. Upload this scan onto your machine.
  3. Use the pen tool in your vector illustration application of choice to trace your signature in one stroke. (this is important, and you'll see why later)
  4. Export the signature vector as an SVG. (not PNG, JPEG, etc)
What if I don't have a vector illustration app already?

Figma is a free and collaborative design web app that has vector illustration tools, like the pen tool.

Once you create and open a design file in Figma, here are the relevant official tutorials that you'll need:

If you've gotten this far, awesome stuff! 🎉. It's time for the next step.

2. Create the Signature Component

In your React repository, create a new file called Signature.jsx (or Signature.tsx for you fellow Typescript fans).

The functional component boilerplate should look like so:

export default function Signature() {
    return (
        <p>Hello World</p>
    )
}

Of course, this simply renders "Hello World" if added to the component tree. We want it to render the SVG that we exported earlier. To do that, we're gonna dive right into the SVG markup. Maybe we'll learn a thing or two.

If you open the SVG of the signature in a text editor, you should see a familiar HTML/XML like markup in this format:

<svg 
    width="108" 
    height="89" 
    viewBox="0 0 108 89" 
    fill="none" 
    xmlns="http://www.w3.org/2000/svg"
>
    <path 
        d="..." 
        style="some styling"
    />
</svg>

All SVG's are wrapped in the svg element. In this case, we only have one path element inside our SVG. Remember Why?

It's super important that it's only one path element because it reduces the complexity of our animation. Animating one path element is so much easier.

Another note is that the d attribute on the path element specifies the bezier curve using curve commands.

Anyway, HTML (and by extension JSX) can render SVGs in two ways:

  1. Using the img element (like any image on the web).
    <img src="vector.svg" alt="You just got Vectored"/>
    
  2. The svg element.

Since we want to animate the SVG, the second option is advantageous. Copy and paste the signature's SVG into your component. It should look something like this:

export default function Signature() {
    return (
        <svg 
            width="108" 
            height="89"
            viewBox="0 0 108 89" 
            fill="none" 
            xmlns="http://www.w3.org/2000/svg"
        >
            <path 
                d="..." 
                style="some styling"
            />
        </svg>
    )
}

3. Animate the Signature Component

It's time to breathe some life into our signature!

If you haven't already, install framer-motion using your preferred package manager:

npm i framer-motion

then add an import for the motion component(s):

import { motion } from "framer-motion"

Motion Components

motion has a set of components which are DOM primitives, but supercharged with smooth animation capabilities. There's a motion component for every HTML and SVG element (including the path element). Each motion component allows you to:

  • Animate via a simple prop.
  • Respond to gestures with animations.
  • Add drag, pan, hover and tap gestures.
  • Deeply animate throughout React trees via variants.

We're gonna be exploring the first two capabilities with the signature.

Animate

Let's swap the svg and path elements with their respective motion components:

export default function Signature() {
    return (
        <motion.svg 
            ...
        >
            <motion.path 
                ...
            />
        </svg>
    )
}


A motion component can take in variants (or keyframes) of the component as a prop that it will transition to and from. We specify these variants with an object.

The variants that I used look like this:

const variants = {
    hidden: {
        pathLength: 0,
    },
    visible: {  
        pathLength: 1,
    }
}


I want the signature to be hidden initially, and gradually become more visible. We specify this with the initial and animate props.

<motion.path
    d="..."

    strokeDasharray="0 1"
    variants={variants}
    initial="hidden"
    animate="visible"
    style="some styling"
/>


Finally, we want to specify some transition details for the animation. We can specify this as follows.

<motion.path
    ...
    transition={{ease: "easeInOut", duration: 2, delay: 0.5}}
/>

The transition prop takes an object that specifies the transition. Read about it here. I'll briefly explain the three values I specified:

  • ease: "easeInOut"

Specifies the easing function to use in the transition. "easeInOut" is one of Framer's built in functions, but you can also specify a custom cubic bezier curve for the easing function. Custom Easing Functions

  • duration: 2

Specifies the duration of the animation. (2 seconds)

  • delay: 0.5

Specifies the delay starting from componentDidMount() to the start of the animation. (0.5 seconds)

Respond to Gestures with Animations

You might not have noticed, but you can hover over the signature, and the signature gets erased, and then redrawn when not hovering. This is super simple with framer-motion:

<motion.path
    ...
    whileHover="hidden"
    ...
/>

This sets the whileHover animation state to be "hidden", and the same transition is applied. Framer Motion is animation magic 🪄.

We did it! 🎊

Now you can draw a signature with the help of React and Framer Motion! Hopefully you're inspired to create some cool, more complex animations with Framer Motion in your React projects.