Animating an svg icon

Page 1

Animating an SVG Icon

[Demo/Download] Implement an animated menu Svg icon. At first, the icon is the classic burger menu icon. But when you click on it, it becomes a close icon with a fun “ninja” effect. The animation is reversed when you click on the close icon which turns it into the initial hamburger icon again. Take a look:

Planning To achieve this effect, I cannot imagine anything better than SVG. And the new library Segment (which is an alternative to the DrawSVGPlugin from GSAP) provides the necessary utilities to implement it. The main idea is to create three paths that describe the trajectory of each bar on the burger icon when it transforms to the close icon. The Segment library will allow us to animate the path strokes in the way we want. To draw paths, any vector editor (like Adobe Illustrator or Inkscape) can be used; in this case we’ll be drawing the paths manually (tying lines, curves and arcs), because we want to get the best possible accuracy. Keep in mind that we are doing an animation that contains “elastic” movements, therefore these must be considered in the length of each path. But before we continue, let’s have a look at Segment.


Introducing Segment The main tool we’ll be using is Segment, a little JavaScript class (without dependencies) for drawing and animating SVG path strokes. Using Segment is pretty straightforward: <!-- Add the segment script (less than 2kb) --> <script src="/dist/segment.min.js"></script> <!-- Define a path somewhere --> <svg> <path id="my-path" ...> </svg> <script> // Initialize a new Segment with the path var myPath = document.getElementById("my-path"), segment = new Segment(myPath); // Draw a segment of a stroke at the time you want // Syntax: .draw(begin, end[, duration, options]) segment.draw("25%", "75% - 10", 1); /* Full example with all possible options */ // Define a normalized easing function (t parameter will be in the range [0, 1]) function cubicIn(t) { return t * t * t; } // Define a callback function function done() { alert("Done!"); } // Draw the complete path segment.draw(0, "100%", 1, {delay: 1, easing: cubicIn, callback: done}); </script>

To learn more you can play with the demo and check out the documentation on GitHub. Also, if you want to understand how Segment works, you can read more about it in this article. It is important to note that Segment does not include any easing function (except the default linear one), so we will be using the excellent d3-ease library for this.

Drawing It’s a very quick animation, but if we analyze the animation frame by frame, we can draw each path. The result is something like this:


Created from the following code we’ve developed piece by piece: <svg width="100px" height="100px"> <path d="M 30 40 L 70 40 C 90 40 90 75 60 85 A 40 40 0 0 1 20 20 L 80 80"></path> <path d="M 30 50 L 70 50"></path> <path d="M 70 60 L 30 60 C 10 60 10 20 40 15 A 40 38 0 1 1 20 80 L 80 20"></path> </svg>

Now we need to add the proper CSS styles to the paths to achieve the desired effect, and an id to access them easily from our script. This is the HTML structure we’ll be using: <!-- Wrapper --> <div id="menu-icon-wrapper" class="menu-icon-wrapper"> <!-- SVG element with paths --> <svg width="100px" height="100px"> <path id="pathA" d="M 30 40 L 70 40 C 90 40 90 75 60 85 A 40 40 0 0 1 20 20 L 80 80"/> <path id="pathB" d="M 30 50 L 70 50"/> <path id="pathC" d="M 70 60 L 30 60 C 10 60 10 20 40 15 A 40 38 0 1 1 20 80 L 80 20"/> </svg> <!-- Trigger to perform the animations --> <button id="menu-icon-trigger" class="menu-icon-trigger"></button> </div>

And the CSS styles:


// The wrapper was defined with a fixed width and height // Note, that the pointer-events property is set to 'none'. // We don't need any pointer events in the entire element. .menu-icon-wrapper{ position: relative; display: inline-block; width: 34px; height: 34px; pointer-events: none; transition: 0.1s; } // To perform the scaled transform for the second demo .menu-icon-wrapper.scaled{ transform: scale(0.5); } // Adjusting the position of the SVG element .menu-icon-wrapper svg{ position: absolute; top: -33px; lef: -33px; } // Defining the styles for the path elements .menu-icon-wrapper svg path{ stroke: #fff; stroke-width: 6px; stroke-linecap: round; fill: transparent; } // Setting the pointer-events property to 'auto', // and allowing only events for the trigger element .menu-icon-wrapper .menu-icon-trigger{ position: relative; width: 100%; height: 100%; cursor: pointer; pointer-events: auto; background: none; border: none; margin: 0; padding: 0; }

Animating With the SVG code ready, our task now is to figure out or to guess the easing functions used in each section of the animation, and to achieve a proper synchronization, always guided by the animated GIF. Let’s see how to animate the top and bottom bars of the hamburger icon. First,


we need to initialize a segment for each bar with the initial begin and end values. Because we don’t have the information at hand but only the visual animation of the GIF, this is a trial and error process until we find the right values. var pathA = document.getElementById('pathA'), pathC = document.getElementById('pathC'), segmentA = new Segment(pathA, 8, 32), segmentC = new Segment(pathC, 8, 32);

With that we are ready to animate, always keeping the same length (end - begin = 24) during the whole animation. Analyzing the animation sequence, we can see that the first part starts with a linear easing function, and ends with an elastic one. We’ll be using functions that receive the segment as a parameter to reuse the same function with the top and bottom bars, because they will be animated in the same way.

[Demo/Download]


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.