Wednesday, May 30, 2012

HTML5 Canvas "Loading" Widget

At work I'm been working on a "on demand" TV portal app for our IPTV service, the app is a fully on demand service so each page of the app has to make multiple ajax calls to get content for display. So as you can imagine I had to use multiple "loading" animations to indicate which sections of the app were being loaded.

* Our IPTV apps are built on a HTML5 compatible engine so we use JavaScript as our primary coding language.

For the "loading" experience I started using animated Gifs but realized that the quality looked terrible on our low powered hardware and it also did not provide the flexibility to use different themes efficiently (e.g. a blue loading image or a red loading image), as for each theme we had to get our designers to create a new animated image (and creating animated gifs are a pain in the a** :)

I then did some research and came across a CSS3 loading effect. Basically, you create some Divs and give them various rotation properties using the CSS3 rotate property (e.g  webkit-transform: rotate(45deg) ). You then use a setTimeout function and keep incrementing the rotation degrees of the Divs. This basically rotates the Divs and gives you the loading effect. This is a good approach but I didn't like how messy the code was, I also suspected that it could have a performance impact on our low powered hardware as each time we rotate the Divs the DOM will be redrawn. (This is not a big issue with PC browsers but on low powered hardware device browsers such as those found on mobile phones and set up boxes, this could cause memory issues).

Enter HTML5 Canvas to the rescue.

I always wanted to build something useful using the Canvas element, but never got the change and this seemed like the perfect opportunity to use it. I was pretty new to canvas to I followed a brilliant tutorial on canvas I found here.

The end result was a loading widget that you can place on your webpage and show and hide it as needed. For the example I've shown below using jsFiddle, I made it look pretty big, but as its all JavaScript you can make it dynamically re-size. For example, on load of the page you can detect the width and height of the Canvas DOM element and recalculate all the width, height, thickness etc. properties of the individual elements that make up the drawing.

Some things to note:
1) This effect is basically a single static drawing that we rotate using a setTimeout function, but unlike the CSS3 solution I described above which also uses the setTimeout method to achieve the animation effect, I believe that Canvas has better performance. This is because Canvas drawings are handled on the pixel level and not the DOM element level.

This quote from the tutorial above also explains this well:
"... In Canvas, transformations are applied before you start drawing the path, shape, or text that you want transformed. That's because what you're transforming isn't an element at all…remember that Canvas doesn't render elements, it renders pixels, and once the pixels are drawn, they're just part of the canvas."

* In the jsFiddle below you can turn off the animation by setting the "animateTheLoader" variable to false to see what the static image looks like.

2) In Canvas almost everything you draw is done using various points in your canvas placed in  X, Y coordinates and then connecting them together. This can make things a bit hard to follow, so I use a "Guide Grid" that I use when I develop (This idea is also given in the tutorial above).

* I've enabled the Guide Grid by default in the jsFiddle below, but turn it off by setting the "showGuideGrid" to false and see what the end result looks like.

Feel free to reuse this code in your projects.

Happy Coding...

Update 1/7/2012:
I built another jsFiddle to show you both the Canvas loading animation and the CSS3 loading animation side by side. Check it out below.

Canvas animations are slow if no Hardware Acceleration?
I also did this side by side test on our Set Up Box hardware at work, and I was very surprised to see the CSS3 animation outperform the Canvas animation by a massive amount. In fact, the Canvas animation was very slow and lagyy and had our CPU running close to 80%. I suspect this is because our Set Up Box's implementation of the browser on which test was done, does not support Hardware Acceleration.

No comments:

Post a Comment

Fork me on GitHub