Animating SVG paths with .beginElement()

Triggering SVG animate elements with javascript is a thing. Here’s how to do it.

As part of a recent project I wanted to create an SVG navigation icon that animates with state changes on the parent element. In this instance from hamburger menu icon, to back arrow.

Both icons are made up of three lines, so it should be possible to animate nicely between them.

Basic States

Key to this technique working is using (and reusing) an equivalent set of instructions between states (in this instance our three straight lines).

Because of this idea of animating between like-for-like paths we must also use the full L syntax to draw the lines rather than the H shorthand and that we get the whole shebang drawn in a single path.

Here are the Menu and Arrow paths.

//Menu
<path d="M10 10 L 90 10 M10 50 L 90 50 M10 90 L 90 90" />

//Arrow
<path d="M50 10 L 10 49 M90 50 L 10 50 M50 90 L 10 51" />

See the Pen by Marc Heatley (@TheHeat) on CodePen.

In both instances the path is structured as follows: [ move + line + move + line + move + line ] this is important as it means the transformation will be completely predictable.

The SVG animate element

The SVG spec allows us to add limited keyframe (from, to) animations that target a specific attribute associated with a specific element. The animation definition sits inside the <path>  tags.

In this case we’ll be animating the path description. Twice! Here’s the first one:

<animate 
   id="animate-to-arrow"
   attributeName="d"
   // from Menu path
   from="M10 10 L 90 10 M10 50 L 90 50 M10 90 L 90 90"
   // to Arrow path
   to="M50 10 L 10 49 M90 50 L 10 50 M50 90 L 10 51"
   dur="0.25s"
   begin="indefinite"
   fill="freeze"
/>

It’s pretty readable, but the important bits to notice here are the begin=”indefinite” which means the animation doesn’t fire immediately and fill=”freeze” which holds the final state.

Triggering an animation with beginElement();

Now we have the animation defined, we need it to run on demand. We do this by targeting the animate elements by ID and wrap them a function using the .beginElement() method.

iconToArrow = document.getElementById('animate-to-arrow');

function animateIconToArrow(){
  iconToArrow.beginElement();
}

Here’s a simple demo

See the Pen by Marc Heatley (@TheHeat) on CodePen.