Clock Blog
Visualising live data with the HTML5 canvas
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:
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 calleddrawShapeIncrementFromEqual()which takes an argument calledprogress. - Our
drawPie()method should now repeatedly call thedrawShapeIncrementFromEqual()passing theprogressargument between 0 and 1. - The
drawShapeIncrementFromEqual()should draw the chart at its start position ifprogress = 0, and at it's finishing position ifprogress = 1, and a linear progression for all values between. - Now in our
drawPie(), instead of passing ourprogressvariable 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.
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!
Like what you've read?
