Creating accessible charts using canvas and jQuery
Posted by Scott on 03/05/2008
Data visualization in HTML has long been tricky to achieve. Past solutions have involved non-standard plugins, proprietary behavior, and static images. But this has changed with the recent growth in support for the new HTML Canvas element, which provides a native drawing API that can be addressed with simple Javascript. This article is a proof of concept for visualizing HTML table data with the canvas element.
The idea of visualizing HTML table data has been a hot topic lately. The first mention of it that we have seen was Christian Heilmann's YUI blog entry, which provides a clean solution for the problem using the Yahoo library. The idea is a good one: having the data on the page in a table allows it to be accessible, and the chart can be shown as a visual enhancement. Our attempt at solving the problem uses jQuery and provides several types of graphs, such as Pie, Line, Area, and Bar.
So how does it work?
First the markup:
We start with a regular old HTML data table like the one shown below:
<table id="dataTable" summary="Member Data from 2000 to 2006"> <caption>Member Data from 2000 to 2006</caption> <thead> <tr> <td></td> <th id="2000">2000</th> <th id="2001">2001</th> <th id="2002">2002</th> <th id="2003">2003</th> <th id="2004">2004</th> <th id="2005">2005</th> <th id="2006">2006</th> </tr> </thead> <tfoot> </tfoot> <tbody> <tr> <th headers="members">Mary</th> <td headers="2000">150</td> <td headers="2001">160</td> <td headers="2002">40</td> <td headers="2003">120</td> <td headers="2004">30</td> <td headers="2005">70</td> <td headers="2006">70</td> </tr> <tr> <th headers="members">Tom</th> <td headers="2000">3</td> <td headers="2001">40</td> <td headers="2002">30</td> <td headers="2003">45</td> <td headers="2004">35</td> <td headers="2005">49</td> <td headers="2006">70</td> </tr> <tr> <th headers="members">Brad</th> <td headers="2000">10</td> <td headers="2001">00</td> <td headers="2002">10</td> <td headers="2003">85</td> <td headers="2004">25</td> <td headers="2005">79</td> <td headers="2006">70</td> </tr> <tr> <th headers="members">Kate</th> <td headers="2000">40</td> <td headers="2001">80</td> <td headers="2002">90</td> <td headers="2003">25</td> <td headers="2004">15</td> <td headers="2005">119</td> <td headers="2006">200</td> </tr> </tbody> </table>
For the charts, we place Canvas elements in the markup with class names that are descriptive of their chart type and source.
<canvas id="chart1" class="fgCharting_src-dataTable_type-pie"></canvas>
As you can see, we've created somewhat of a custom syntax in our class names. The syntax begins with "fgCharting" and is followed by key/value pairs which are separated using underscores and matched using dashes. Using this syntax, the above class name tells our script that the source ("src") is a table with an ID of "dataTable", and our chart type ("type") is Pie. Note: There are many other ways this could be handled, and including the chart settings in the markup may not be the best separation of markup and behavior, but for the purposes of this example it seems to work well.
And now for the Scripting:
Once we have jQuery and our charting library attached, we can convert our canvas elements into charts with the following line of javascript:
$.fgCharting();
A live demo
The following demo uses the markup and scripting mentioned above. For example purposes, the following table is editable, so if you change the values the Pie will redraw in real time!
Cool! What about different charts?
We've developed several other types that can be specified using our library; these are:
- line
- filledLine
- additiveLine
- additiveFilledLine
- pie
- bar
- additiveBar
Since these charts involve different groupings of data, our script organizes the table data in multiple ways. For example, Pie charts need the total table sum, each member's individual total, and each member's name. However, line, bar, and area (filled) charts need to know each member's value at every point on the X scale. Because of these differences, our script collects an object of the following properties and passes it along to the chart builder:
- members: member names
- allData: array of every value in the table
- dataSum: sum of all members in the allData array
- topValue: highest value in the table
- memberTotals: array of totals for each member
- yTotals: array of y-axis totals
- topYtotal: highest value in the yTotals array
- xLabels: labels for the X axis of line, bar, and area charts
- yLabels: labels for the Y axis of line, bar, and area charts
- yLabelsAdditive: y labels for the Y axis of additive charts
More chart types: (data table hidden visually)
The following example shows some more examples of charts that our library can generate.
Grab our script
You can download our charting library source here: fgCharting.jQuery.js
Note: Be sure to download the jQuery javascript library as well, as our charting library depends on it!
Browser support
Canvas is not natively supported in Internet Explorer, but lucky for us, the smart folks at Google have made a patch that uses purely javascript to port Canvas support to IE! We've included their library for our examples and it can be downloaded here: ExplorerCanvas.
Looking ahead
There are many charting libraries out there today that use Canvas and many of them go well beyond what we've demonstrated above. We feel that the major advantage of this technique is that the data is accessible to users on any device. Looking ahead, we hope to develop a library that is much more focused on retrieving the table data in a way that is similar to accessing a database with SQL statements. This library would then allow its data to be sent to more advanced charting libraries such as Flot, to create truly dynamic data visualizations.
Comments
Good job! This looks really promising.
If you don’t mind, some feature requests: I have been looking out for a few of these types of implementations, but one thing I find in common is that they all seem to lack labels and legends in the charts—for example the pie chart has the percent which is nice, but it would be nice if it could have the actual headings/labels in there, as well as a legend of what each colour refers to (for the colour-blind, etc).
Perhaps using information from the markup, such as the scope, headers, axes, ids, etc or extra classes could be used to indicate what labels to show, etc?
These would be handy in the bar and line charts potentially too, as well as the ability to indicate whether labels go inside, outside, best fit, etc…
Comment by Anup on 03/26 at 10:37 AM
line 44
this parent.node is null
using IE 6
Comment by matt on 03/26 at 05:39 PM
Great Job!
Comment by Dragan Bajcic on 03/26 at 08:24 PM
Your interactive tables do not work in IE… also the percentage markers in the pie graph are not in the correct places… I would love to use this but these issues make it not much more than a toy…
Comment by Anonymous on 03/27 at 09:57 AM
patched to make it work for pages with multiple data tables. see http://pastie.org/181257
thanks for the library!
Comment by choonkeat on 04/15 at 02:29 PM
I have been looking at chart generation with canvas for some time and as a jQuery lover, this looks very promising. I am hoping I will be able to use this at a local elections count, where we deliver both the results live on the web but also on plasma screens in the counting hall.
This could be just fantastic, thank you so much for your hard work on producing what looks to be something that is utterly marvelous!
Comment by Vicky Lamburn on 04/26 at 02:03 PM
Nice script - although I can’t quite seem to get any graph other than a pie to update on the fly changing the td member data. It seems to be updating the y axis labels, but the actual canvas element doesn’t change at all with different data. Any ideas?
Comment by Sean on 04/29 at 07:12 PM
I have recently joined the jQuery club and am enjoying the stuff that is possible.
This is another great display of what can be done.
Great Work and thanks for the article....
Comment by Daniel on 05/21 at 09:05 PM
Great example, but it doesn’t works with jQuery 1.2.6…
Am I missing something?
Best Regards,
Pedro Martins
Comment by Pedro Martins on 06/02 at 09:13 AM
This doesn’t seem to be working in Safari 2
Comment by Robert E on 06/09 at 11:46 AM
you can check our user interface library too. here is the web http://myjui.com/latestbuild/mj/res/myjui/examples/
please, let me know what you are thinking about it.
Comment by ozi on 06/16 at 06:00 AM
You should update fgCharting for the current version of JQuery. It doesn’t work with 1.2.6!
Comment by Dan Cole on 07/13 at 01:29 PM
Incredible! Thanks much.
Comment by Alexander Obenauer on 07/29 at 04:05 PM
I always miss examples of bar charts with negative values. This is where most of the available plotting libraries / frameworks fails and having this kind of example really saves time for people evaluating alternatives.
Comment by Jorge on 08/10 at 10:12 AM
Vraiment très sympa, et en restant toujours accessible!!
Comment by Paco on 08/10 at 03:00 PM
Great script! Unfortunately, it doesn’t work with jQuery 1.2.6
Comment by co. on 08/20 at 05:23 AM
BTW, where and how do I pass “topValue”??? I would appreciate for example. Tnx
Comment by co. on 08/20 at 07:16 AM
Wow! any ideas on when would be it available for jQuery 1.2.6??
Comment by Rob on 08/28 at 12:57 PM
Thanks ya you have great idea
Comment by ahmedabad on 09/01 at 05:01 PM
It’s bad when a page have two or more table,the chats is wrong.However this is correctly great script.
Comment by hezhen on 09/05 at 08:22 PM
Any plans to support jquery 1.2.6?
Great job!
Comment by johnnyrock on 10/02 at 08:12 PM
Great script ! Thanks, I ‘m going to try to make it work with the latest jQuery ... Stumbled !
Comment by Jack on 10/28 at 05:10 AM
To work with jquery 1.2.6 you can do it:
on row 431 add
var tableObj = this;
on rows 436, 526 change
$(this).find -> tableObj.find
zakwer
Comment by zakwer on 10/30 at 09:47 AM
@zakwer: Awesome! Thanks, we’ll check that out.
Comment by Scott (Filament) on 10/30 at 09:55 AM
We’ve updated this script with changes suggested by @zawker so this now works with jQuery 1.2.6. Thanks @zawker!!
Comment by Scott (Filament) on 10/31 at 12:29 PM
Nice jQuery component. Good job.
Question: How do you resize the chart. I tried to resize the barchart to make it bigger with no luck.
The default size for the barchart is width: 300 and height: 15 or 30em and 15em. I tried modifying the width and height to 18 and 36 with no luck, and I looked at the source code and tried to modify the default sizes there.
Any easy way to resize the barchart? The default size is too small, I think.
Comment by Tom on 11/12 at 11:40 AM
This plug-in has verygood features, but i am getting problems while implementing it.I didn’t find any information here regarding canvas, you converting the canvas elements in to pie charts…
Comment by Nagmalleswara Rao on 01/02 at 03:04 AM
Great list of jQuery learning tools at:
http://www.jquerybasics.com
Comment by Jack Larson, Admin on 01/16 at 03:08 PM
As canvas is not supported by default in Intenet Explorer, you can use ExplorerCanvas http://excanvas.sourceforge.net/ to add this functionality to it
Comment by Peter Schmalfeldt on 01/18 at 01:29 AM
Has anyone else noticed that in the “More types” examples, the bar charts are cropped off on the left side, meaning the first columns in any canvas are always shorter than they should be?
Is this possible to fix within fgCharting.js?
Comment by Tetsuo on 01/21 at 05:14 AM
Great plugin! Nice work! Does this work with jquery-1.3.1?
Comment by Ferdie Domingo on 02/03 at 08:49 AM
Nice library, thanks. Great JoB \o/
Comment by Ahmet ERTEM on 02/04 at 09:43 AM
great charts, thx
Comment by trendbender on 02/08 at 04:37 AM
This will surely ease up the process of our reporting requirements. Tnx for sharing this great plugin!
Comment by Filipino Web Designer on 02/08 at 08:58 AM
Is there any way to drill down on the Pie chart, Please suggest.
Comment by HImanshu Kansal on 02/16 at 01:18 AM
Good job! thanks
Comment by Maxim Shipko on 02/21 at 05:18 AM
To say that the introduction of the canvas element was met with mixed reactions from the web standards community, I think that this is a fantastic example of what can be done. I will certainly look to incorporate this in my next website design. Thanks for all the hard work .
Comment by PS Website Design on 02/27 at 01:08 PM
It should be noted that the charts will not size correctly if the base font size is anthing other than 62.5%
Comment by Jamie Thompson on 03/23 at 09:49 AM
I am having trouble getting this to work in fire fox 3.0.7. Only about 1/4 of the chart is showing. Anyone have any ideas why? Works fine in EI7
Comment by Brandon on 03/25 at 01:15 PM
The default size is 300px x 150px. How can I scale it (line graph)? When I change the canvas width/height, there is only a part of the graph.
Comment by star on 03/26 at 12:05 PM
Very nice and useful, Thanks mate!!
Comment by Martin Gonzalez on 03/27 at 06:53 AM
How Does It Works In Chinese. I Download One Of These Samples,And I Just Changed The Title From English To Chinese Characters.Finaly,I Found That The Chinese Characters Doesn’t Displayed At All.But The English Characters Was Displayed Well.It’s Must Be Some Mistake In My Codes Or System Entironment Which I Didn’t Kown Completly.Besides , I Am Not Very Sure Whether You Has Understand My Expression.I Am A Chinese Boy With Very Poor English . Please Pardon Me.
Comment by zhao Junhua on 04/07 at 01:55 AM
How do you set the minimum y axis value? Best charting script I’ve found.
Easy to get going, and having the table data display is just the ticket.
Thanks.
Comment by Dana Elza on 05/06 at 07:45 PM
would be epic if it would work with Library v1.3.2 :(
Comment by hannes on 05/07 at 05:34 AM
Hi, i guess you forget to mention that you have to take a look of the style, otherwise it won´t work
Comment by Pepe on 05/08 at 09:37 PM
Very useful, Thanks alot
Comment by Bui tan thao on 05/21 at 12:38 AM
Nice library,Thanks!!
I’m building and testing new web site.
But I didn’t have graph’s jQuery library.
I’ll try to develop it . Bye Bye.
Comment by nobutaka on 05/31 at 10:06 AM