Speziell für Tortendiagramme wird die Funktion d3.layout.pie()
Daten mit den Attributen startAngle
und endAngle
formatieren. Der Radius kann beliebig sein (wie weit vom Zentrum entfernt Sie das Etikett platzieren möchten).
Wenn Sie diese Informationen mit einigen trigonometrischen Funktionen kombinieren, können Sie die x- und y-Koordinaten für Etiketten bestimmen.
Betrachten Sie dieses gist/block.
Was die x/y-Positionierung des Textes betrifft, steckt das Magische in dieser Zeile (für bessere Lesbarkeit formatiert):
.attr("transform", function(d) {
return "translate(" +
( (radius - 12) * Math.sin( ((d.endAngle - d.startAngle) / 2) + d.startAngle ) ) +
", " +
( -1 * (radius - 12) * Math.cos( ((d.endAngle - d.startAngle) / 2) + d.startAngle ) ) +
")";
})
((d.endAngle - d.startAngle) / 2) + d.startAngle
gibt uns unseren Winkel (Theta) in Radiant.
(radius - 12)
ist der willkürliche Radius, den ich für die Position des Textes gewählt habe.
-1 *
die y-Achse ist invertiert (siehe unten).
Die verwendeten trigonometrischen Funktionen sind: cos = Ankathete / Hypotenuse
und sin = Gegenkathete / Hypotenuse
. Aber es gibt ein paar Dinge, die wir berücksichtigen müssen, damit diese mit unseren Etiketten funktionieren.
- Der 0-Winkel ist um 12 Uhr.
- Der Winkel nimmt immer noch im Uhrzeigersinn zu.
- Die y-Achse ist invertiert gegenüber dem Standard-Koordinatensystem. Positives y ist in Richtung 6 Uhr - nach unten.
- Positives x ist immer noch in Richtung 3 Uhr - nach rechts.
Das bringt einiges durcheinander und hat im Grunde den Effekt, dass wir sin
und cos
vertauschen. Unsere trigonometrischen Funktionen werden dann: sin = Ankathete / Hypotenuse
und cos = Gegenkathete / Hypotenuse
.
Wenn wir Variablennamen substituieren, haben wir sin(Radiant) = x / r
und cos(Radiant) = y / r
. Nach etwas Algebra können wir beide Funktionen in Bezug auf x und y erhalten r * sin(Radiant) = x
und r * cos(Radiant) = y
. Danach stecken Sie diese einfach in das transform/translate-Attribut.
Dadurch platzieren Sie die Etiketten am richtigen Ort. Um sie ansprechend aussehen zu lassen, benötigen Sie eine Styling-Logik wie diese:
.style("text-anchor", function(d) {
var rads = ((d.endAngle - d.startAngle) / 2) + d.startAngle;
if ( (rads > 7 * Math.PI / 4 && rads < Math.PI / 4) || (rads > 3 * Math.PI / 4 && rads < 5 * Math.PI / 4) ) {
return "middle";
} else if (rads >= Math.PI / 4 && rads <= 3 * Math.PI / 4) {
return "start";
} else if (rads >= 5 * Math.PI / 4 && rads <= 7 * Math.PI / 4) {
return "end";
} else {
return "middle";
}
})
Dadurch werden die Etiketten von 10:30 Uhr bis 1:30 Uhr und von 4:30 Uhr bis 7:30 Uhr in der Mitte verankert (sie befinden sich über und unterhalb), die Etiketten von 1:30 Uhr bis 4:30 Uhr an der linken Seite verankert (sie befinden sich rechts) und die Etiketten von 7:30 Uhr bis 10:30 Uhr an der rechten Seite verankert (sie befinden sich links).
Die gleichen Formeln können für jeden D3-Radialgraphen verwendet werden, der einzige Unterschied liegt darin, wie Sie den Winkel bestimmen.
Ich hoffe, das hilft allen, die darauf stoßen!