Animate your SVG text with animejs (and Vue)

Animate your SVG text with animejs (and Vue)

Are you looking for a non-standard portfolio page welcome text? Do you want to create an animated website to propose to your loved one?

Say no more!

In this #showdev I'll teach you how to create stunning SVG animation with an equally stunning animejs library!

The result will look like this:

Gif of result

NOTE: This post will show you how to create a line drawing animation in animejs. If you want it in a condensed form, straight from the source, visit the official documentation.

Prerequisites

To create a stunning animated SVG image, first, you will need SVG to animate. There are many tools to do that, available both online and offline. You can, for example, start with generating text using easysvg (written in php, but a great tool nonetheless).

Important: Every letter in your SVG should be a separate <path> tag! Here paths mark the outlines of the letters.

You will also need a container to run the animation in. It can be anything, pure JS script or a more advanced app. In my case, I'm using a very simple Vue.js app.

Preparing your SVG

To make our SVG look classy, we need to tweak it a bit:

  1. To provide it with an "outlined" look, set fill attribute in every <path> tag to transparent and set stroke attribute to any color you want.

  2. Add some extra elements for flavor - directly in SVG code (if you're the pro and a math nerd) or use some editor to do it.

Use my SVG, if you want: link to github file.

Animating

First, install animejs. %[github.com/juliangarnier/anime]

Then add animejs animation:

anime({
    targets: document.getElementsByTagName('svg')[0].children,
    strokeDashoffset: [anime.setDashoffset, 0],
    easing: 'easeInOutBack',
    delay: function(el, i) { return i * 250 },
    direction: 'normal',
  });

Easy? Let me break it down line by line!

    targets: document.getElementsByTagName('svg')[0].children,

In this line, we point to every element we want to animate, in this case to an array of every child element of our SVG. You may need to adjust it a little to the structure of your SVG.

    strokeDashoffset: [anime.setDashoffset, 0],

This is what makes animation happen. It uses stroke-dashoffset attribute. If you want to know more about animating SVGs using this attribute, I recommend this CSS Tricks article.

    easing: 'easeInOutBack',

I wanted to add a little "bouncing" at the beginning and the end of the animation of every letter. If you want to test different easing functions on your own, I recommend easings.net.

    delay: function(el, i) { return i * 250 },

I wanted to slightly delay every animated path, so I passed a function that multiplies the delay by the index of an element in the table I passed in targets.

    direction: 'normal',

You can choose from normal, reverse, and alternate.

Embed this... somewhere

Although animejs can be used in Vanilla, I really wanted to use it in my Vue.js app.

I used Vue.js transitions to do that. More on them.

First, template:

<Transition appear :css="false" @enter="onEnter" name="howdy">
  <!-- Your SVG goes here. I used v-html because I'm lazy ¯\_(ツ)_/¯  -->
  <div v-html="howdy" />
</Transition>

You can use SVG Component to embed your SVG on a page.

I wanted my animation to start on a component render, so I added appear keyword to the transitions. I also needed to tell Vue this animation would be purely JS, so I used :css="false".

Now I only need to write onEnter callback:

const onEnter = (el: Element, done: () => void) => {
  anime({
    targets: el.getElementsByTagName('svg')[0].children,
    strokeDashoffset: [anime.setDashoffset, 0],
    easing: 'easeInOutBack',
    delay: function(el, i) { return i * 250 },
    direction: 'normal',
    complete: () => {
      done();
    },
  });
}

onEnter uses the Transition Element as the first argument and done() function as the second. We have to call done() function at the end of the application to signal to Vue that the animation ended. We can use complete hook from animejs to do it. And we want to animate only descendants of our Transition element, so we can specify targets using the first argument.

And... that's it! Sit back and enjoy your animated text!

If you have any questions, I'm happy to answer :) If there's anything to be improved in this short post, let me know, and I'll gladly fix that!

And if you want to see this animation in action, you can visit my page (I have to warn you though, this is still in a WIP stage).

All the best,

Aleksandra (or Ola, for short)