Skip to content

Instantly share code, notes, and snippets.

@jonurry
Created April 17, 2018 08:50
Show Gist options
  • Save jonurry/4809474dff6be0e3f068f4969ff90bed to your computer and use it in GitHub Desktop.
Save jonurry/4809474dff6be0e3f068f4969ff90bed to your computer and use it in GitHub Desktop.
17.2 The Pie Chart (Eloquent JavaScript Solutions)
<canvas width="600" height="300"></canvas>
<script>
let cx = document.querySelector("canvas").getContext("2d");
let total = results
.reduce((sum, {count}) => sum + count, 0);
let currentAngle = -0.5 * Math.PI;
let centerX = 300, centerY = 150, radius = 100;
cx.font = "16px Helvetica";
cx.fillStyle = "black";
// Add code to draw the slice labels in this loop.
for (let result of results) {
let sliceAngle = (result.count / total) * 2 * Math.PI;
let textAngle = currentAngle + sliceAngle / 2;
cx.beginPath();
cx.arc(centerX, centerY, radius,
currentAngle, currentAngle + sliceAngle);
currentAngle += sliceAngle;
cx.lineTo(centerX, centerY);
cx.fillStyle = result.color;
cx.fill();
cx.fillStyle = 'black';
cx.textBaseline = 'middle';
if (Math.cos(textAngle) > 0) {
cx.textAlign = 'start';
} else {
cx.textAlign = 'end';
}
cx.fillText(
result.name,
centerX + Math.cos(textAngle) * radius * 1.1,
centerY + Math.sin(textAngle) * radius * 1.1
);
}
</script>
@jonurry
Copy link
Author

jonurry commented Apr 17, 2018

17.2 The Pie Chart

Earlier in the chapter, we saw an example program that drew a pie chart. Modify this program so that the name of each category is shown next to the slice that represents it. Try to find a pleasing-looking way to automatically position this text, which would work for other data sets as well. You may assume that categories are big enough to leave ample room for their labels.

You might again need Math.sin and Math.cos, as described in Chapter 14.

@jonurry
Copy link
Author

jonurry commented Apr 17, 2018

Hints

You will need to call fillText and set the context’s textAlign and textBaseline properties in such a way that the text ends up where you want it.

A sensible way to position the labels would be to put the text on the line going from the centre of the pie through the middle of the slice. You don’t want to put the text directly against the side of the pie but rather move the text out to the side of the pie by a given number of pixels.

The angle of this line is currentAngle + 0.5 * sliceAngle. The following code finds a position on this line, 120 pixels from the center:

let middleAngle = currentAngle + 0.5 * sliceAngle;
let textX = Math.cos(middleAngle) * 120 + centerX;
let textY = Math.sin(middleAngle) * 120 + centerY;

For textBaseline, the value "middle" is probably appropriate when using this approach. What to use for textAlign depends on the side of the circle we are on. On the left, it should be "right", and on the right, it should be "left" so that the text is positioned away from the pie.

If you are not sure how to find out which side of the circle a given angle is on, look to the explanation of Math.cos in Chapter 14. The cosine of an angle tells us which x-coordinate it corresponds to, which in turn tells us exactly which side of the circle we are on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment