I always loved programming. In the days when Flash was all the rage, I spent hours and hours writing Actionscript: making page transitions as smooth as possible. But alas, all good things come to an end and Flash is no exception. After Steve Jobs rant about Flash it gradually disappeared from the internet. And with Flash, my daily practice in programming disappeared as well. Missing code, I tried Java for a while but never had as much fun with it as I had with Actionscript. I also tried Arduino, and although that was fun, it wasn't very good in what I was looking for in a programming language: making stuff happen on screen.
Part I: The maths of the pie
Before we start writing code, we first need to dive into some maths. If we look at a pie chart, it's not really a circle but a collection of triangles, rounded on one side and neatly put together. This matters because we need to draw slices, not a circle. First, forget about the pie and think of a normal coordinate system like this.
fig 1: a simple coordinate system
You can draw a circle on the coordinate system with a function using sine, cosine and the angle from the (positive) x-axis. The red dot in fig. 2 is what we need to draw our pie. The position of the dot is determined by the angle a and can be expressed in x and y coordinates using sine and cosine: x = sin(a) and y = cos(a). Plotting x and y for all possible a's will create a circle with a radius of 1. But we only need parts of the circle. So how do we know what corner a should be? For this, we're going to use radians. Radians are like degrees: a way of saying how big or small an angle is. A full circle is 2 × π Radians (or 360 degrees) and a full circle represents the total value of the pie. Now we can calculate a for every slice by dividing the amount of the slice by the total amount of the pie and multiply that by 2π:
fig 2: using radians to calculate the angle of the slice with sine and cosine
We can now calculate every starting and ending point on the circle for every slice. The first starting point is on the x-axis and its ending point can be calculated by the functions above. The ending point of each slice is the starting point for the next slice, except for the last slice of course. Now there is one more thing to take into account when calculating the positions. Because we want to align the slices next to each other in a circle we need the cumulative value of all previous slices (fig-3). That's it! You now know all the math needed for drawing a pie chart. So let's dive into SVG and draw it in the browser!
fig 3: use cumulative values to calculate the position of each slice
Part II: Creating a pie chart with SVG
Now that we know the maths we can start drawing our pie chart with SVG. First, let's create a fake data set to visualize:
Extraterrestrial page views (22)
Let's start a new HTML file and place an SVG element in it and define the viewBox like this:
<html> <body> <svg viewBox="-100 -100 200 200"> </svg> </body> </html>
Remember the coordinate system in the first part? SVG has a similar coordinate system and the viewBox property tells the browser how to crop that system. The first pair of properties are the the x and y coordinates of the crops starting position. The second pair of properties are the width and height of the crop. This means we have a viewBox of 200 by 200 with the origin exactly in the center. It is important to notice that the coordinate system is flipped over the y-axis (so positive values are below the x-axis).
Now let’s draw the slices. We're going to use SVG's path element for this. With the path element, you already guessed it, you can draw free paths from point to point (instead of primitives like circle or rectangle). We're going to draw the slices of our pie from the center to the outside, then follow the circle for a while and then back to the center again (see fig-4).
fig 4: direction of the path strokes, clockwise because of the reversed y-axis
To draw the whole pie we need to calculate point C for all slices, so let's do this. When calculating the coordinates we'll multiply the result by 100 so it'll fit neatly into our viewBox. Remember to use cumulative values for calculating the coordinates!
fig 5: Calculations needed to retrieve the coordinates
If we imagine these coordinates, the first signs of the pie chart can be seen:
fig 6: The coordinates. Remember SVG has a vertically flipped coordinate system
It starts on the positive x-axis and we can see that Mars takes up more than half of the pie (which makes sense because 12 divided by 22 is more than one half). Now that we have all coordinates, we can start drawing the slices. Let's draw the first slice: Mars. To do this, we need to draw a path from the center (0 ; 0) to (100 ; 0). Then we need to draw an arc (-95.9 ; -28.2) and then back to (0 ; 0). This will look like this in SVG:
<path d="M0,0 L100,0 A100,100 0 1,1 -95.9,-28.2 Z" />
The first time I saw this code I was genuinely intimidated, so let's break it down and see what it all means. First let's create the (self closing) path element that we're used to in HTML and define the d-parameter which describes the path: <path d="" />. We start with moving the drawing position to the center of the coordinate system: M0,0. We then draw a line to the first point on the circle: L100,0. Now it gets interesting. We want to draw a curved line to the next point. To do this, we need to define the arc: A100,100. In SVG you always define an arc as an ellipse with x and y-radius. Because we want a circle we use the same value twice. And because we want the arc to match the pie chart, we set them at 100. The next parameter is the rotation of the ellipse. We don't want to rotate so we leave this value at 0. Before we define where to end the arc, we first need to set the large-arc-flag and the sweep-flag. The large arc flag tells the browser if it needs to draw more than half of an ellipse. So let's take a look at Mars' value and the total value: there were 12 visitors from Mars and 22 in total: that's more than half from mars so we set the large arc flag to 1 (for all other slices it will be 0 off course). The sweep flag tells the browser in which direction to draw: positive or negative angles. We want positive angles so we set this value to 1. Now the browser knows how to curve the line, we can give it the end coordinates: -95.9,-28.2. We only need to close the path and we're done with our slice. To close the path end it with a Z. That's it! Repeat this for all other slices and you have your pie chart:
<html> <body> <svg viewBox="-100 -100 200 200"> <path d="M0,0 L100,0 A100,100 0 1,1 -95.9,-28.2 Z" /> <path d="M0,0 L-95.9,-28.2 A100,100 0 0,1 65.5,-75.6 Z" /> <path d="M0,0 L65.5,-75.6 A100,100 0 0,1 95.9,-28.2 Z" /> <path d="M0,0 L95.9,-28.2 A100,100 0 0,1 100,0 Z" /> </svg> </body> </html>
Now that's a bit disappointing, isn't it? A dull black circle... what's the point of that? Well, actually, this is exactly what we were looking for. Because all the slices have the same style it looks like a circle but its actually a collection of black slices without a stroke. So let's apply some styles and make a real pie chart out of it:
<html> <body> <svg viewBox="-100 -100 200 200"> <path d="M0,0 L100,0 A100,100 0 1,1 -95.9,-28.2 Z" fill="#c60f1d" /> <path d="M0,0 L-95.9,-28.2 A100,100 0 0,1 65.5,-75.6 Z" fill="#232323" /> <path d="M0,0 L65.5,-75.6 A100,100 0 0,1 95.9,-28.2 Z" fill="#aeaeae"/> <path d="M0,0 L95.9,-28.2 A100,100 0 0,1 100,0 Z" fill="#eeeeee" /> </svg> </body> </html>
Now this looks more like it. The only thing we need to do now is rotate the pie 90 degrees anti clockwise so it looks like a regular pie chart. We place all the slices in a group and rotate the group -90 degrees:
<html> <body> <svg viewBox="-100 -100 200 200"> <g transform="rotate(-90)"> <path d="M0,0 L100,0 A100,100 0 1,1 -95.9,-28.2 Z" fill="#c60f1d" /> <path d="M0,0 L-95.9,-28.2 A100,100 0 0,1 65.5,-75.6 Z" fill="#232323" /> <path d="M0,0 L65.5,-75.6 A100,100 0 0,1 95.9,-28.2 Z" fill="#aeaeae"/> <path d="M0,0 L95.9,-28.2 A100,100 0 0,1 100,0 Z" fill="#eeeeee" /> </g> </svg> </body> </html>
The code above will result in this pie chart:
Fig 7: The final pie chart