Clock Blog

Visualising live data with the HTML5 canvas

Posted on Wednesday, 3 November 2010 @ 17:14 GMT in creative-blogs by Ben Gourley

I've been doing some research into representing live statistics visually in web pages. Live meant that bespoke images weren't an option, and I was reluctant (and not well versed enough in the technology) to use flash. This was a perfect opportunity to look in to canvas. Armed with a signed and printed HTML5 Canvas Cheat Sheet (thanks Dom), Jack and I got busy.

If you're impatient, then skip over to the demo: HTML5 Canvas Chart Demo.

The Idea

We wanted to make something worth using the canvas for. It seemed pointless to draw a simple bar chart in canvas when that can be achieved with divs (or any of your favourite generic elements), so we opted to deal in circles, arcs and radians; firstly a form of pie chart, and secondly 'floating blobs'. However, we didn't want to neglect those not lucky enough to own a decent web browser. When browsers encounter tags they don't understand, their content is still rendered – the way it's dealt with may differ, but we can be sure that if we populate the canvas tags with fallback content, it will be displayed in any browser that doesn't support canvas. What's even better, is that although the content between the canvas tags is not rendered by the browsers that do support it, the contents still exist in the DOM. This is great – we only need one representation of our data; it can reside inside the canvas element and be fetched with Javascript for drawing.

Building It

Inside our canvas element, we decided to store our data in an HTML table, shock horror, but that's ok – it's semantic. This data is retrieved by the Javascript and stored in an array for drawing.

Firstly, we did a bit of normalising of our data. For the pie chart we needed to give each piece of data a proportional slice of the circle, and for the blobs it seemed sensible to give them values to add up to 100%. To draw the pie chart, we used the arc() method with a large stroke size. We also varied the stroke size based on the magnitude of the data which gives a nice dynamic effect. For the blobs, we used the Polar Co-ordinate System to divide the circle up in to equal angles based on how many data points there are, and plot the blobs with a radius based on the size of the data.

Here's a screenshot of the result:

HTML5 Canvas Charts

So that's all pretty and stuff, but it lacks bells and whistles. We decided to introduce some animation and easing. The process goes something like this:

  • We want the pie to start off with equally sized sections that animate to represent the data we've got.
  • We've got a draw-once type function drawPie(). Let's factor out the all of the drawing to another method called drawShapeIncrementFromEqual() which takes an argument called progress.
  • Our drawPie() method should now repeatedly call the drawShapeIncrementFromEqual() passing the progress argument between 0 and 1.
  • The drawShapeIncrementFromEqual() should draw the chart at its start position if progress = 0, and at it's finishing position if progress = 1, and a linear progression for all values between.
  • Now in our drawPie(), instead of passing our progress variable straight to the drawing method, we can run it through a custom easing method. Here we've chosen a nice bouncing ease.

Here's what we've ended up with.

Creating the Fallback

With a bit of CSS and some help from jQuery we can make the fallback data look nice, and even animate in some bar charts. The check for canvas support is simple: getElementById("myCanvasId").getContext will be undefined if canvas is not supported. Take a look at the fallback in your normal canvas capable browser; I've broken the canvas tag to make the fallback kick in.

Canvas fallback.

Unfinished Business

The thing that these charts are missing most is a key. What use is the data if we don't know what it represents? Obviously if we were to use this in a real-life situation then we would make one, but we confess we spent longer on tweaking the easing method than worrying about this!

If you haven't looked at the demo in IE (any version) yet, then don't! It is displaying the fallback content, but the fallback Javascript isn't executing. There are two things that could happen from here: either it's not possible for the javascript to interact with content inside an unrecognised tag. This is the worst case, and I doubt its likelihood, but it could just be styled with some simple CSS. Otherwise IE's not happy with some of the Javascript (somewhat more likely I think), and we could just fix that. I'll save this for a rainy day though, unless anyone would like to offer up any ideas!

blog comments powered by Disqus