The HTML5 canvas element certainly opens a lot of possibilities for web developers. Inspired by Arne @ 23inch.de’s JS1K.com submission I thought I would explore the canvas elements capabilities by creating a simple javascript function that generates a pie chart.

## The Canvas

First we need a canvas element.

<canvas id="c"> Your browser does not support the canvas element. </canvas>

Next we need the script that will draw the Pie Chart. I decided to use two functions; one for the wedge and the other to to loop through the data.

## The Wedge Function

I adapted Arne’s function for drawing arcs to draw wedges.

function W(x,y,r,u,v) { if(r) { a.beginPath(); a.moveTo(x,y); a.arc(x, y , r, (u||0)/50*Math.PI, (v||7)/50*Math.PI, 0); a.lineTo(x,y); a.fill(); } else { a.fillStyle = '#'+'a000b4bbff95'.substr(x,3); } return W; }

x and y are the coordinates of the charts center. r is the radius of the chart. u is the startAngle and v is the stopAngle in percent. Wedge color aka fillStyle is set by x when r is missing. The colors available are interlaced. The function returns itself so that it can be call likeĀ `W(0)(100,100,50,0,25);`

## The Chart

Next I needed a function that would use the wedge function the draw each wedge of the pie chart.

function pie(r,b,n) { c.width=3.5*r; c.height=2.5*r; x=y=c.height/2; a.font="bold 12pt Arial"; var u = 0; var v = 0; for (i=0;i < b.length;i++) { v+=b[i]; W(i)(x,y,r,u,v); u=v; a.fillText(n[i],x+r+10,y-r/2+i*18); } }

Again r is the radius and is used to calculate the canvas’ height and width and variables x and y. b is an array of the percents and n is an array of the names used for the charts key. The function loops through the elements of the array, drawing each wedge and key. It is assumed that the elements of b total 100.

## Bringing the pieces together

Lastly, create the needed arrays and call the pie function which in turn calls the wedge function.

var n = ['RED','BLACK','BLUE','GREEN','PINK']; //key names for each wedge var b = [20,25,15,10,30]; //percents, needs to total 100 pie(100,b,n);

Again it is assumed that b’s elements total 100 and that n and b have the same number of elements.

## What it looks like

So if you are using an HTML5 compliant browser you get this:

For any developer that consider readability and maintainability important I refactored the code:

`function pieChart(canvas, radius, percentages, labels, colors) {`

var canvas = document.getElementById(canvas)

var context = canvas.getContext("2d");

canvas.width = 3.5*radius;

canvas.height = 2.5*radius;

var cx, cy;

cx = cy = canvas.height/2;

context.font = "bold 12px Arial";

var start_rad = 0;

var end_rad;

var end_percentage = 0;

for (i = 0; i < percentages.length; ++i) {

end_percentage += percentages[i];

end_rad = end_percentage / 100 * 2 * Math.PI;

context.fillStyle = colors[i];

drawWedge(context, cx, cy, radius, start_rad, end_rad);

start_rad = end_rad;

context.fillText(labels[i], cx + radius + 10, cy - radius/2 + i*18);

}

}

`function drawWedge(context, cx, cy, radius, start_rad, end_rad) {`

context.beginPath();

context.moveTo(cx,cy);

context.arc(cx, cy , radius, start_rad, end_rad, false);

context.lineTo(cx,cy);

context.fill();

}

Hey Ruben,

This function is no longer working in the latest version of Chrome. Any ideas what’s up with it?

I can confirm that on Chrome Version 26.0.1410.43 m the wedges are not drawn. It goes back to Magnus’ comment about “readability and maintainability”. The code for the wedge

`a.beginPath() | a.fill(a.moveTo(x,y)|a.arc(x,y,r,(u||0)/50*Math.PI,(v||7)/50*Math.PI,0)|a.lineTo(x,y))`

is the issue; probably cause the pipes. I updated the function to this`function W(x,y,r,u,v) {`

and it now works.if(r) {

a.beginPath();

a.moveTo(x,y);

a.arc(x, y , r, (u||0)/50*Math.PI, (v||7)/50*Math.PI, 0);

a.lineTo(x,y);

a.fill();

} else {

a.fillStyle = '#'+'a000b4bbff95'.substr(x,3);

}

return W;

}

Edit: Changing the actual wedge to

`a.beginPath() | a.moveTo(x,y) | a.arc(x,y,r,(u||0)/50*Math.PI,(v||7)/50*Math.PI,0) | a.lineTo(x,y) | a.fill()`

works too.Ah Sweet! Thanks a lot Reuben – Works great again now.