-
-
Save jonurry/4809474dff6be0e3f068f4969ff90bed to your computer and use it in GitHub Desktop.
<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> |
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.
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
andMath.cos
, as described in Chapter 14.