Animated SVG loading Icon

2016-12-04 00:00:00 by Mike

Animated SVG elements are nothing to be intimidated by. In this write-up and demo we'll learn how to create a smoothly animated SVG icon using widely supported HTML, CSS and JavaScript. See the stand-alone demo here.

First, some basics. SVG, first defined in 1999, stands for scalable vector graphics and is based on mathematical points, rather than pixel units. The main benefits of SVG are scalability and increased independence from rasterized image files (for example: .gif, .png, .jpg files).

Now for the code for creating the animated SVG icon (see the stand-alone demo here).

The HTML and CSS are fairly simple, listed below in Figure 2. Notice the svg and path elements in the HTML are based on XML syntax. The svg element sets the bounds of the element and the path is a line composed of points. The "d" attribute of the path element stands for "description". The "M", for "move to", in the value of d represents the x and y coordinates where the path will begin. The CSS sets the size of a div containing the svg, and rotates that div continuously around its center in 2 second periods.

The JavaScript, listed below in Figure 3, controls the animated length of the path element. As shown in Figure 1 above, the path is actually composed of many 5 degree arcs arranged adjacent to one another. The arcs, or radians, listed in the "d" attribute of the path element are converted to an array. This is done to more easily add and remove radians from the path.

That's it! I hope you enjoyed this write-up, and please share it if you found it useful.

Figure 1 (below): The solid SVG path is actually composed of many five degree arcs arrange adjacently.

Figure 2 (below): The HTML & CSS for the animated loading icon.

<style> #container { width:200px; height:200px; -webkit-animation:spin 2s infinite; -moz-animation:spin 2s infinite; -webkit-transform-origin: 50% 50%; -moz-transform-origin: 50% 50%; transform-origin: 50% 50%; } @-moz-keyframes spin { from { -moz-transform: rotate(0deg); } to { -moz-transform: rotate(360deg); } } @-webkit-keyframes spin { from { -webkit-transform: rotate(0deg); } to { -webkit-transform: rotate(360deg); } } </style> <div id="container"> <svg xmlns="" xmlns:xlink="" version="1.1" viewBox="0 0 200 200" id="loader" onload="drawCircle();"> <path d="M0,0 " id="arc" fill="none" stroke="#f75" stroke-width="20" /> </svg> </div>
Figure 3 (below): JavaScript that controls the addition and removal of arc segments from the SVG path element.
<script> function drawCircle() { "use strict"; var i = 0, angle = 0, radius = 75, shrink = false, updatedDescriptionArray = [], pathElement = document.getElementById("arc"); window.timer = window.setInterval( function() { // Shrink the arc when it reaches 360 degrees in length, otherwise grow the arc when it shrinks to 5 degrees. if (angle > 0 && angle%360===0) { shrink = true; } else if (angle === 5) { shrink = false; } if (shrink === true) { angle -= 5; } else { angle += 5; } // Calculate the coordinates of the radian we are going to add next var radian = (angle/180) * Math.PI; var x = 100 + Math.cos(radian) * radius; var y = 100 + Math.sin(radian) * radius; // Set pathDescription equal to the 'd' (description) attribute of the element var pathDescription = pathElement.getAttribute("d"); var descriptionString, newMoveTo; if (i == 0) { // Starting coordinates for the path on initial page load updatedDescriptionArray.push(" M " + x + " " + y); } else { if (shrink === false) { // Grow the path: add line-to point for each radian updatedDescriptionArray.push(" L " + x + " " + y); } else { // Shrink the path: define a new point for move-to based on the second line-to point newMoveTo = updatedDescriptionArray[1].replace("L","M"); // Remove the first radian updatedDescriptionArray.splice(1,1); // Update the starting point of the path updatedDescriptionArray.splice(0, 1, newMoveTo); } } var descriptionString = updatedDescriptionArray.join(" "); // Update the description attribute of the path pathElement.setAttribute("d", descriptionString); i++; }, 25); } </script>