Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

Animated Loading Image with SVG

4.78/5 (4 votes)
17 May 2014CPOL3 min read 19.8K   81  
Create an animated SVG to use as a loading image.

Introduction

For years, it has been standard practice to provide the user with an animated “loading” or “working” image whenever an application or program does something that takes more than a few milliseconds.

For example:

Loading...

or:

For us in the web environment, this practice presented a slight bit of a challenge because the only way we could do it was by making an animated GIF image. This can be very difficult if you’re a programmer and not a graphics designer. The task was also further complicated because our favorite graphics software (Photoshop) does not support the making of animated GIFs. In fact, finding the right GIF animator is a challenge all by itself. In addition to that, GIF supports a very limited number of colors so making a good looking loading image was mission impossible. Thankfully, the invention of HTML5 washed away all these worries.

HTML5 introduced a multitude of ways to present the user with an animated loading image without having to spend hours making tons of GIF images. In particular, HTML5 gave us the canvas and the SVG. After spending a few hours investigating the differences between an animated GIF, Canvas, and SVG, I decided to make a loading image that I can use across all my web pages as needed using SVG.

Why SVG

Between an animated GIF, Canvas, and SVG, the GIF has the worst performance. It requires the most CPU usage. In addition, you are limited by the colors and lack of decent software. The performance difference between Canvas and SVG is minimal. The Canvas, however, requires significantly more code to animate. For example, for each frame of the animation, the Canvas must be cleared, and then the whole image must be redrawn. On the other hand, the SVG simply requires the elements inside it to be altered as necessary for each frame. This can be done with much less code. Lastly, as we all know, SVG is scalable that means it is easy to take an existing animated SVG and make it larger or smaller for different applications. And that is why I chose the SVG.

The Loading Image

To make things simple, I first of all created my SVG image:

HTML
<svg id="loadingImg1" width="100" height="100">Loading...

  <circle cx="80" cy="50" r="5" fill="#000080"/>

  <circle cx="74" cy="32" r="5" fill="rgba(0,0,180,0.8)"/>

  <circle cx="59" cy="21" r="5" fill="rgba(0,0,180,0.6)"/>

  <circle cx="40" cy="21" r="5" fill="rgba(0,0,180,0.4)"/>

  <circle cx="26" cy="32" r="5" fill="rgba(0,0,180,0.2)"/>

</svg>

By placing the elements of the image inside the markup instead of adding them dynamically, the speed of the code is improved and made more reusable.

Then to maintain reusability, I coded a wrapper for my SVG that will raise an event each time the next frame must be loaded.

JavaScript
//svg: the object reference to the svg element
//frames: the number of frames in the animated image
//delay: the time (in milliseconds) between each frame
function AnimatedImg(svg, frames, delay) {
    /****some code omitted for brevity****/

    //if onnextframe is assigned to a function it will be called periodically as determined by the frames variable
    this.onnextframe = null;

    //the elements of that make up the SVG
    this.elements = new Array(0);

    //currentFrame ranges from 1 to the number given by frames
    this.currentFrame = 1;

    this.isAnimated = function (){}
    this.startAnimation = function () {}
    this.stopAnimation = function () {}
}
//frames not given because AnimatedImg assigns default 10
//delay not given because AnimatedImg assigns default 100
var loadingImg1 = new AnimatedImg(document.getElementById("loadingImg1"));

For the full definition of AnimatedImg function, see the source code. As demonstrated in the source code, the AnimatedImg can be used to animate more than one SVG on a single page, and it can be used for any SVG regardless of the internal structure of the SVG. To use it in your own projects, download it via NuGet (the key is AnimatedImg).

The next step is to define the function where all the magic happens, and assign it the onnextframe event of the AnimatedImg. This function will then be called every 100 milliseconds. It uses the currentFrame property of the AnimatedImg to determine which frame to display and consequently where each element of the SVG must be.

JavaScript
loadingImg1.onnextframe = animateLoadingImg;
function animateLoadingImg(){
       for(var l_1 = 0;l_1<this.elements.length;l_1++)
       {
              this.elements[l_1].setAttribute("cx",
                   getX(30,(Math.PI/5*this.currentFrame)-(Math.PI/5)*l_1)+50);

                  this.elements[l_1].setAttribute("cy",
                   getY(30,Math.PI/5*this.currentFrame)-(Math.PI/5)*l_1)+50);
       }
 }
function getX(radius,angle){
        return Math.cos(angle)*radius;
    }
function getY(radius,angle){
        return Math.sin(angle)*radius;
    }

The final step is to call the startAnimation method to animate the SVG and the stopAnimation method to stop the animation.

//start animation and display svg
loadingImg1.startAnimation();

//stop animation and hide svg
loadingImg1.stopAnimation();

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)