Ich werde ein Textelement in jeden Bogen meines Kreisdiagramms (Mitte) einfügen - wie in diesem Beispiel gezeigt: Ссылка
Aber ich werde das Textelement nur einfügen, wenn der Raum für den ganzen Text ausreicht, also muss ich die Größe meines Textelements mit dem "verfügbaren" Leerzeichen in jedem Bogen vergleichen.
Ich denke, dass ich dies mit getBBox () tun kann, um die Textdimensionen zu erhalten ... aber wie kann ich die Dimension des verfügbaren Raums in jedem Bogen erhalten (und vergleichen).
thx ...!
Diese Frage wurde wurde mehrmals zuvor angefragt.
Die Lösungen, die ich vorgeschlagen habe, sind rotate
das Label, aber es hat mich nie ganz zufrieden gestellt. Ein Teil davon war das schreckliche Font-Rendering, das von einigen Browsern durchgeführt wurde, und der Verlust an Lesbarkeit, der das bringt, und das seltsame flip
, wenn ein Label die 180°
-Zeile kreuzt. In einigen Fällen waren die Ergebnisse akzeptabel und unvermeidbar, z. wenn die Etiketten zu lang waren.
Eine der anderen Lösungen, die von Lars vorgeschlagen wurde, besteht darin, die Etiketten außerhalb des Tortendiagramms zu platzieren. Das schiebt jedoch nur die Labels nach außen, was ihnen einen größeren Radius verleiht, aber das Problem overlap
nicht vollständig löst.
Die andere Lösung verwendet tatsächlich die Technik, die Sie vorschlagen: entfernen die Etiketten, die nicht passen.
Vergleichen Sie Original mit >= 65
label, das zu Lösung wo das überlaufende Label verschwunden ist.
Die wichtigste Erkenntnis besteht darin, dass bei diesem Problem festgestellt wird, ob ein konvexes Polygon ( ein Rechteck , die Bounding Box) in einem anderen konvexen Polygon ( -ish ) ( ein Keil ).
Das Problem kann reduziert werden, um herauszufinden, ob alle Punkte des Rechtecks innerhalb des Keils liegen oder nicht. Wenn dies der Fall ist, liegt das Rechteck innerhalb des Bogens.
Jetzt ist dieser Teil einfach. Alles, was Sie tun müssen, ist zu überprüfen:
radius
startAngle
und endAngle
des Bogens. Jetzt, wo wir das aus dem Weg haben, wird im zweiten Teil herausgefunden, was die vier Ecken des Rechtecks sind. Das ist auch einfach:
%Vor% Das Mark der Lösung befindet sich in der Funktion each
. Wir platzieren den Text zuerst an der richtigen Stelle, so dass das DOM ihn rendert. Dann verwenden wir die getBBox()
-Methode, um die Bounding-Box von text
in der Benutzerbereich Ein neuer Benutzerbereich wird von jedem Element erstellt, für das ein transform
-Attribut gesetzt ist darauf . Dieses Element ist in unserem Fall die Box text
. Der zurückgegebene Begrenzungsrahmen ist also relativ zur Mitte des Textes, da text-anchor
auf middle
gesetzt wurde.
Die Position von text
relativ zu arc
kann berechnet werden, da wir die Transformation 'translate(' + arc.centroid(d) + ')'
darauf angewendet haben. Sobald wir das Zentrum haben, berechnen wir nur die topLeft
, topRight
, bottomLeft
und bottomRight
Punkte daraus und sehen, ob sie alle in wedge
liegen.
Schließlich bestimmen wir, ob alle Punkte innerhalb des Keils liegen und wenn sie nicht passen, setzen Sie die Eigenschaft display
CSS auf none
.
Ich benutze die innerRadius
welche, wenn nicht Null, die wedge
nicht-konvex macht, was die Berechnungen viel komplexer macht! Ich denke jedoch, dass die Gefahr hier nicht signifikant ist, da der einzige Fall, in dem es scheitern könnte, dies ist, und ehrlich gesagt denke ich nicht, dass es oft passieren wird (ich hatte Schwierigkeiten, dieses Gegenbeispiel zu finden):
x
und y
werden umgedreht und y
hat ein negatives Vorzeichen während der Berechnung von Math.atan2
. Dies liegt an der Differenz zwischen der Darstellung von Math.atan2
und d3.svg.arc
im Koordinatensystem und der Richtung positiver y
mit svg
.
Koordinatensystem für Math.atan2
θ = Math.atan2(y, x) = Math.atan2(-svg.y, x)
Koordinatensystem für d3.svg.arc
θ = Math.atan2(x, y) = Math.atan2(x, -svg.y)
Das können Sie nicht wirklich mit der Begrenzungsbox tun, da die Begrenzungsbox viel größer als ein Keil für die Keile des Kreisdiagramms ist. Das heißt, obwohl der Keil am äußeren Rand breit genug wäre, um den Text aufzunehmen, bedeutet das nicht, dass er an der tatsächlichen Position des Textes breit genug ist.
Leider gibt es keine einfache Möglichkeit, das zu tun, was Sie versuchen (Pixel-Level-Overlap-Test). Siehe z.B. diese Frage für weitere Informationen. Ich würde vorschlagen, die Textbeschriftungen einfach außerhalb des Tortendiagramms zu platzieren, damit Sie nicht auf dieses Problem stoßen.
Tags und Links javascript html svg d3.js