Created
April 17, 2018 08:50
-
-
Save jonurry/4809474dff6be0e3f068f4969ff90bed to your computer and use it in GitHub Desktop.
17.2 The Pie Chart (Eloquent JavaScript Solutions)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hints
You will need to call
fillText
and set the context’stextAlign
andtextBaseline
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:For
textBaseline
, the value"middle"
is probably appropriate when using this approach. What to use fortextAlign
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.