Animated handwriting effect (part 1)

In part 1 of this post, I covered how to trace a cursive font with the pencil tool in Adobe Illustrator so we can create an animated handwriting effect. You’ll need some open paths with a stroke to make this work.

In part 2, I’ll show you how to animate the drawing of the path strokes. We'll also be adding an element that will follow the paths and move from the end of one path to the beginning of the next one.

Let's start with some GSAP

I’m going to be using GreenSock’s animation platform for this process. Specifically, TweenMax and my favorite plugins:

  • DrawSVG: this will be the main workhorse that draws the path. Yes, you can make the JavaScript calculations on your own, but this plugin deals with several browser fussiness issues that would normally drive you crazy.
  • MorphSVG: the name implies it’s for morphing (and it is), but it’s got a cool method called MorphSVGPlugin.pathDataToBezier() that takes an SVG path and converts it into an array of points along which we can animate something. Hmmm…. sounds like the perfect way to move a hand or pencil along our handwriting path.

Full disclosure: I am a huge fan of GreenSock and highly recommend GSAP and all the incredible plugins to anyone looking to save time in their work. I do volunteer some time over there as a forum moderator. Between Jack and Carl and all of the moderators and members, we can answer any questions you have about the platform.

The plugins I'm using in this post are premium plugins as part of Club GreenSock, but you can test any of them for free on CodePen. See this GreenSock demo for the links.

Drawing the paths

The DrawSVG plugin makes drawing SVG strokes incredibly easy. Say you have a path in your SVG like this:

    <path id="path1" d="M169.2,107c-.71,70.36,47.26,138.58,113.71,161.71s146.42-.56,189.55-56.15c17.44-22.48,29-49,45.37-72.22s40-44.08,68.32-46.44c24.27-2,47.89,10,66,26.36s31.74,36.83,46.67,56.07c25.95,33.43,56.77,64,94.37,83.42s82.7,26.77,122.9,13.54,73.74-49.21,77.86-91.33" fill="none" stroke="#fff" stroke-linecap="round" linejoin="round" stroke-miterlimit="10" stroke-width="4"/>

Assuming you have all the JavaScript files loaded, all you need to animate it is one line of code:

  TweenMax.fromTo("#path1", 1,  {drawSVG:"0% 0%"}, {drawSVG:"0% 100%"});

That’s all you need to do for your handwriting paths. You would then sequence all the tweens on a timeline and the paths would draw on one by one for a cool handwriting effect. You could stop right there and have a nice animation, but what if we could have a hand, pencil or paintbrush follow the path and look like it was writing it? Getting an element to follow along the path as it draws takes a bit more work, but it’s not too hard.

Follow the path

Using the MorphSVG plugin and its awesome MorphSVGPlugin.pathDataToBezier() method we can create a path for our element to follow. Again, assuming the path from the above HTML snippet, we can create a motion path like this:

  var motionPath1 = MorphSVGPlugin.pathDataToBezier("#path1", {align: "#target"});

To animate the target along the path, you simply create a tween and have it follow our newly created motionPath1.

  // in this case, our target is a simple circle, but you can use anything 
// including groups or images... well, anything...
TweenMax.to("#target", 3, { bezier:{values:motionPath1, type:"cubic"}})

Now we can put the draw effect and motion path together. In the following demo you'll see the target circle follow path 1 and then move to the beginning of path 2. Path 2 draws its stroke as the circle animates along it. This is done by starting the two tweens at the same time on the timeline. Smooth and easy.

Extra position data

Okay great, we've got a target moving along a path and it draws a stroke as it moves, but wait a minute... there's a couple extra tweens in there that animate to some strange x/y position. What's that about? Uh-oh! Is there gonna be math? Or something super complicated that involves an abacus?

Nope. It'll be easy. Those are just the starting coordinates of the next path. Once the circle target finishes its run along path 1, we don't want it to just snap to the beginning of path 2 so we need to tween it over there. Where do these coordinates come from though?

That data comes from the array of points we have in our motion path. A simple console log will help us:

  // this will give us the array of points in the motion path
console.log(motionPath2);

// open the array and we'll see several objects
// check out the first one and you'll see the coordinates we need
// you should see something like this
0:Object
x:160.52
y:479.74

Plug that data into a tween and that's how you make your target move from the end of one path to the beginning of the next path. That comes in really handy when you move from one handwritten word to the next.

Whether you have two paths or twenty, you can have it move to the next path gracefully rather than snapping over there. You'll notice in the above demo I also tween back to the start of path 1 at the end of the timeline. This creates a nice seamless loop.

Putting it all together

So, you've seen how to draw the stroke of the paths and have a target element go along for the ride. Now all you need to do is sequence your handwriting paths and whatever element you'd like to simulate the drawing.

Let's assume we've gotten our motion path data from the MorphSVG plugin for a couple of paths. We also have made notes about the starting x/y position of path 2. You just need to sequence all the tweens on a timeline to put it all together and make it work. It would look something like this.

  TweenMax.set("path", {drawSVG:0});// set all path strokes to 0
var tl = new TimelineMax();
tl.add("start") // use a label to start tweens at the same time
tl.to("#path1", 3,  {drawSVG:true}, "start"); // draw path 1
tl.to("#target", 3, { bezier:{values:motionPath1, type:"cubic"}}, "start"); // follow path 1
tl.to("#target", 2, {x:100, y:500}); // move to path 2 starting point 
tl.add("label"); // use a label to start tweens at the same time
tl.to("#path2", 3,  {drawSVG:true}, "label"); // draw path 2
tl.to("#target", 3, { bezier:{values:motionPath2, type:"cubic"} }, "label"); //follow path 2
tl.to("#target", 2, {x:500, y:800}); // move to path 3 if you have more
// lather, rinse, repeat

The final result

I've added some speed and stroke color controls to my version just for fun. It looks more complicated, but most of the code is related to the controls. If you look at the actual timeline, you'll see it's the exact same procedure that I demonstrated above with the two paths and the circle target element. Draw along a path, tween to the next, draw along a path, tween to the next, etc. Here's my final version:

Closing thoughts

You can use this technique to make some nice handwriting effects, but it can be used for so much more. Create a pencil icon that draws a set of blueprints or a pair of shoes that follow a path on a map. Imagine the possibilities.

For more info about GSAP or any of the plugins I used, please check out the GreenSock website or stop by the GSAP forums and chat with everyone. It's a fun and friendly community.

I have more posts and demos in the works. If you want to say hi, I'm on Twitter @Craig_PointC or you can always find me on the GreenSock forums.

I hope you found some of this useful. See ya next time.


3,281 5 58