Canvas pie

February 5th, 2008. Tagged: canvas, JavaScript

UPDATE: Translation in Brazilian Portuguese here, thanks Maujor!

OK, so you have an HTML table. Let's turn it into a pie chart with a bit of javascript.

We'll be using the canvas tag, so the browser has to support it. For IE - well, you still have the table. That's why we'll call it progressive enhancement. Unobtrusive too. Here's a screenshot:
canvas-pie.png

» The demo is here (refresh for new colors)

Here are the ingredients to the recipe:

  1. One <canvas> tag
  2. One <table> full of data
  3. javascript to get the data from the table
  4. javascript to plot the data on the canvas

One canvas tag

<canvas id="canvas" width="300" height="300"></canvas>

One table full of data

This is a bare bone unstyled old school table.

<table id="mydata">
    <tr>       <th>Lang</th><th>Value</th> </tr>
    <tr><td>JavaScript</td>  <td>100</td>  </tr>
    <tr><td>       CSS</td>  <td>200</td>  </tr>
    <tr><td>      HTML</td>  <td>300</td>  </tr>
    <tr><td>       PHP</td>  <td> 50</td>  </tr>
    <tr><td>     MySQL</td>  <td> 30</td>  </tr>
    <tr><td>    Apache</td>  <td> 10</td>  </tr>
    <tr><td>     Linux</td>  <td> 30</td>  </tr>
</table>

javascript to get the data from the table

First, some setup. Let's tell the script which is the ID of the data table, the ID of the canvas tag and which column contains the data:

// source data table and canvas tag
var data_table = document.getElementById('mydata');
var canvas = document.getElementById('canvas');
var td_index = 1; // which TD contains the data

Next, select all table rows, then loop through the rows, selecting all TDs. Add the data we need to a data array. While at it, run a total of the data in the column and also create an array of random colors. Paint each row with the selected color. (we'll see the actual getColor() in a bit.)

var tds, data = [], color, colors = [], value = 0, total = 0;
var trs = data_table.getElementsByTagName('tr'); // all TRs
for (var i = 0; i < trs.length; i++) {
    tds = trs[i].getElementsByTagName('td'); // all TDs
 
    if (tds.length === 0) continue; //  no TDs here, move on
 
    // get the value, update total
    value  = parseFloat(tds[td_index].innerHTML);
    data[data.length] = value;
    total += value;
 
    // random color
    color = getColor();
    colors[colors.length] = color; // save for later
    trs[i].style.backgroundColor = color; // color this TR
}

javascript to plot the data on the canvas

Time for the fun part, the drawing! First, we need to create a context object. Then figure out the raduis of the pie and the center, all based on the width/height pf the canvas tag:

// get canvas context, determine radius and center
var ctx = canvas.getContext('2d');
var canvas_size = [canvas.width, canvas.height];
var radius = Math.min(canvas_size[0], canvas_size[1]) / 2;
var center = [canvas_size[0]/2, canvas_size[1]/2];

Next, let's loop through data and paint pieces of the pie. To draw a piece of pie, you basically need to call these methods of the context object:

  • beginPath() - to start the piece of the pie
  • moveTo() - to set the pencil in the center
  • arc() - draw a piece of a circle
  • lineTo() - finish the circle piece with a line back to the center
  • closePath() and fill() but set the fill color first.

Here's the actual code for this part, hopefully the comments help:

var sofar = 0; // keep track of progress
// loop the data[]
for (var piece in data) {
 
    var thisvalue = data[piece] / total;
 
    ctx.beginPath();
    ctx.moveTo(center[0], center[1]); // center of the pie
    ctx.arc(  // draw next arc
        center[0],
        center[1],
        radius,
        Math.PI * (- 0.5 + 2 * sofar), // -0.5 sets set the start to be top
        Math.PI * (- 0.5 + 2 * (sofar + thisvalue)),
        false
    );
 
    ctx.lineTo(center[0], center[1]); // line back to the center
    ctx.closePath();
    ctx.fillStyle = colors[piece];    // color
    ctx.fill();
 
    sofar += thisvalue; // increment progress tracker
}

utility

Here's the function that gives a random color:

    // utility - generates random color
    function getColor() {
        var rgb = [];
        for (var i = 0; i < 3; i++) {
            rgb[i] = Math.round(100 * Math.random() + 155) ; // [155-255] = lighter colors
        }
        return 'rgb(' + rgb.join(',') + ')';
    }

C'est tout! Enjoy your pie :D

UPDATE: Comment by Zoltan below, if you use Explorer Canvas, you can make this work in IE with only this:
<!--[if IE]><script type="text/javascript"
src="/path/to/excanvas.js"></script><![endif]-->

Tell your friends about this post: Facebook, Twitter, Google+

42 Responses

  1. [...] I love it when a plan comes together (removes cigar): After I played with Google charts and porting the idea of generating charts from accessible table data over to YUI charts Stoyan Stevanof had to use the same idea to generate his own, home-made Canvas-driven charts: [...]

  2. My browser (IE7 [Vista Home Premium]) shows JS-error.

  3. [...] I love it when a plan comes together (removes cigar): After I played with Google charts and porting the idea of generating charts from accessible table data over to YUI charts Stoyan Stevanof had to use the same idea to generate his own, home-made Canvas-driven charts: [...]

  4. Thanks Alexey, fixed now. I’m now checking if canvas is supported, my bad for claiming that it’s OK in IE without testing :)

    Before the lat step (drawing) I now do:

    if (typeof canvas.getContext === 'undefined') {
        return;
    }
    
  5. [...] I love it when a plan comes together (removes cigar): After I played with Google charts and porting the idea of generating charts from accessible table data over to YUI charts Stoyan Stevanof had to use the same idea to generate his own, home-made Canvas-driven charts: [...]

  6. This is beautiful! Too beautiful.
    I tested with Mac Safari, FF, and windows XP Ie7 and no browser has problem displaying this beautiful thing! Thank you!

  7. In IE6 it wont`t show up (i mean the pie), only html table showed. Other browsers (FF 2.0.11, Opera 9.25) show both, pie and table.

  8. Yes, Janek, IE6 don’t understand the canvas tag

  9. [...] phpied.com It’s your responsibility to die() if necessary… – PHP Manual « Canvas pie [...]

  10. I got this to work in IE using ExplorerCanvas (http://excanvas.sourceforge.net/). By adding one line in the :

    You can get this working nicely in IE.

    Hope this is useful to someone.

    Z.

  11. Hmmm … I see this doesn’t entify tags … let me try one more time.

    I got this to work in IE using ExplorerCanvas (http://excanvas.sourceforge.net/). By adding one line in the head, you can get this working nicely in IE.

    Hope this is useful to someone.

    Z.

  12. [...] phpied.com » Blog Archive » Canvas pie (tags: javascript charting canvas accessibility programming google graph code chart table webdev web development) [...]

  13. Cool stuff, very useful.
    I’ve wrapped up a quick jquery plugin around your code, the post is at http://blogs.atalayasec.org/dev/?p=9

  14. [...] This is very flattering: Greg Houston took my script for DIY canvas pie and added tooltips and better colors logic. Here’s the result, it’s really nice, built with some MooTools. The tooltips are not supported in <canvas> but Creg used an image that overlays the pie and set the tooltips with an image map. Clever, isn’t it? [...]

  15. Excellent article. I’ve added values and indicators in my version. Check it out at http://www.mattknott.com/content/blog/2008/04/Advanced_Canvas_Based_Pie_Chart.html

  16. hey guys want to draw some animated chart’s, look what i have found visifire powered by silverlight offered under open source. just for Nothing(free)

  17. my script for DIY canvas pie and added tooltips and better

  18. Hmmm … I see this doesn’t entify tags … let me try one more time.

  19. Very useful thanks, although im somewhat of a novice, this go’s a long way in helping me learn

    many thanks again
    Dave

  20. [...] the original here: Canvas pie / phpied.com Share and [...]

  21. [...] This post was Twitted by davidrvega – Real-url.org [...]

  22. It’s lightweight, works great. I think it’s more readable if the data is pre-sorted large to small. I also swapped out the color function with the one used by Greg Houston
    http://blog.greghoustondesign.com/canvas-pie-chart-with-tooltips/
    just because I wanted the colors to be bolder and consistent. Thanks a lot for doing this!

  23. great code samples for canvas beginners

    text to canvas

    1.
    how I can put entire html document to a canvas ?
    including ofcourse it’s font design , so it will be looked on canvas as the original html

    2. get ‘text’ drawed in canvas
    how on mouse over on canvas or drawing rectangle zone I can get the text ‘under’ ?

    any code sample or link will be appreciated

  24. beautifully done, like a work of art. I’m interested in uitilising this feature more for my own personal use. I’ve checked out the below version and it is worth a look:

    http://www.mattknott.com/content/blog/2008/04/Advanced_Canvas_Based_Pie_Chart.html

  25. Hmmm … I see this doesn’t entify tags … let me try one more time.

    I got this to work in IE using ExplorerCanvas (http://excanvas.sourceforge.net/). By adding one line in the head, you can get this working nicely in IE.

    Hope this is useful to someone.

    http://www.doktortr.net/

  26. how do you do if you want six pie chart in one page?

  27. Mit den besten Wuenschen fuer frohe Weihnachts Feiertage. Greetings and best wishes for a happy Christmas.

  28. Excellent job!!!

    But it seems that recent versions of Internet Explorer need this line in the header of html to display the chart:

    (insert this line before ….)

    Cheers

  29. Sorry Here below the line missing:

    <meta http-equiv=”X-UA-Compatible” content=”IE=7″&gt:

  30. I would like know a way to write data to the canvas from a JavaScript Array instead of from a table.

    if you have an answer, please contact me via http://ngranger.110mb.com/Files/Contact_Form.html

  31. [...] of a Pie Chart that I used for inspiration – and to borrow some JavaScript code from: http://www.phpied.com/canvas-pie/. Tags: canvas, dbms_epg, listagg Share this [...]

  32. I have a complicated task to do where I need to get the (x, y) of the end angle, the point where the line is drawn back to the center and cuts the pie pieces. In this case, it would be each of the points at the end of the radius at ‘Math.PI * (- 0.5 + 2 * (sofar + thisvalue)),’

    I can’t figure out how to find each of those points, I know all that is needed exists in order to find it but not sure how to calculate it.

    Anyone have any ideas?

  33. this is not worked for me

  34. please provide code snippet that works in IE 8.

  35. [...] HTML 5 Canvas Pie Charts Source: Stoyan Stefanov Excerpt: [...]

  36. [...] of a Pie Chart that I used for inspiration – and to borrow some JavaScript code from: http://www.phpied.com/canvas-pie/. canvas dbms_epg [...]

  37. Scott, it’s nice to meet you. I hope Shutterstock will continue to accept my scientific work. Shutterstock now has a educational micrograph (photos taken with a microscope) section second to none.

  38. Well, I’m not going to value this site unless they create such a system that I might able to download foods right from my screen. lol

  39. Wow… HTML5 charts are simply awesome. No more plugins or extra features. Nice. But I was wondering about a fallback if the browser does not support HTML5 then? I guess in that case, it must be replaced by an image or something similar… Do you have any better option?

  40. Hi there, its fastidious post concerning media print, we all understand media is a great source of information.

  41. Hi there! Do you use Twitter? I’d like to follow you if that would be okay. I’m definitely
    enjoying your blog and look forward to new posts.

  42. Thanks for sharing, this was very useful to me.

Leave a Reply