2016-05-15 9 views
4

Ich bin ein chart mit D3.js, die einige Informationen über die Kompetenzen der Mitarbeiter zeigt.Umbruch Text auf kreisförmigen Textpfad

Screenshot: enter image description here

Wie Sie sehen können, einige Text größer als Containerelement Größe, weil der, dass ein Teil des Textes, geschnitten wird. Ich möchte diese Texte in einen Container verpacken.

Ich habe this example gefunden, aber ich konnte keine Lösung für mein Diagramm anwenden.

Hilfe würde geschätzt ...

Hier ist charts codepen url und hier ist full screen view

P. S. Ich brauche Text, um mit Worten verpackt zu werden

+0

Möchten Sie mit Wörtern oder Buchstaben umbrechen? (für den Fall, dass ein Wort nicht in den verfügbaren Platz passt) – iulian

+0

Ich wollte mit Worten, aber von jetzt an denke ich, es wird nicht schwer sein, Ihre Lösung zu transformieren, um meine Bedürfnisse zu erfüllen – bumbeishvili

+0

hmm ... Es war schwer: s – bumbeishvili

Antwort

2

Um die Etiketten zu wickeln, müssen Sie Mikes Lösung anpassen, um mit textPath Elementen umzugehen.

Dafür brauchen wir mehrere Dinge:

1. die zur Verfügung stehende Breite Holen, die

wickeln sollten die Etiketten erreichen Sie die Länge des Bogens berechnen konnte selbst, aber ich habe dies getan, indem Berechnen des Segments, das von den Endpunkten Ihrer unsichtbaren Pfade erstellt wird, denen Ihre Labels folgen. Dies wird uns auch einen kleinen Seitenrand geben, da die Länge des Segments kürzer ist als die Länge des Bogens.

Der Abstand zwischen zwei Punkten berechnet sich wie folgt:

d = sqrt((x2 - x1)^2 + (y2 - y1)^2)

2. Wickeln Sie die Etiketten, wenn sie reich verfügbare Breite und halten die

für diesen einen zum Zentrum ausgerichtet Verwaltung, hatte ich in die SVG Dokumentation über die textPath element zu graben, um zu sehen, wie es entlang der Y-Achse gewickelt und verschoben werden kann.

Anfangs habe ich versucht, mehrere textPath Elemente innerhalb eines text Labels zu setzen, aber ich konnte es nicht schaffen, sie entlang der y-Achse zu verschieben. Es stellt sich heraus, dass Sie dafür tspan Elemente innerhalb textPath Elemente hinzufügen müssen. Aber hier entstand ein anderes Problem - ich konnte es nicht schaffen, sie zentriert zu halten.

Um eine Verschiebung entlang der y-Achse und der zentralen Ausrichtung zu erreichen, müssen Sie am Ende ein Element textPath (für horizontale Ausrichtung) mit einem Element tspan innen verwenden (für vertikale Ausrichtung).

3. Wickeln Sie die Etiketten mit den Buchstaben, nicht durch Worte

dies der Punkt ist, dass ich angenommen habe, dass man nämlich Brief Verpackung benötigen (im Moment des Schreibens, ich habe nicht die Antwort aus OP), weil auf kleinen Größen Ihres Diagramms Wörter zu lang sind, um in eine Zeile zu passen.

Dies war das einfachste Problem zu lösen.Gerade die Spaltung einstellen und Fügeoperationen von Worten zu Buchstaben wechseln:

letters = text.text().split('').reverse(); // instead of .split(/\s+/) 
... 
tspan.text(line.join("")); // instead of .join(" ") 

Und hier ist der gesamte Code, der geändert wurde, mit Bemerkungen:

outerSvg.selectAll(".outerCircleText") 
    .data(pie(behaviorsDatasetOuterCircle)) 
    .enter().append("text") 
    .attr("class", "outerCircleText") 
    //Move the labels below the arcs for those slices with an end angle greater than 90 degrees 
    .attr("dy", function (d, i) { 
     d.i = i; 
     return (d.startAngle >= 90 * Math.PI/180 ? 18 : -11); 
    }) 
    .text(function(d) { return d.data.name; }) 
    .call(wrap); // Do not add `textPath` elements here. Instead, add them in the `wrap` function 

function wrap(text) { 
    text.each(function() { 
    var text = d3.select(this), 
     letters = text.text().split('').reverse(), 
     letter, 
     line = [], 
     lineNumber = 0, 
     lineHeight = 1.1, // ems 
     y = text.attr("y"), 
     dy = parseFloat(text.attr("dy")), 
     textPath = text.text(null).append("textPath") // Add a textPath element 
      .attr("startOffset", '50%') 
      .style("text-anchor", "middle") 
      .attr("xlink:href", function(d) { return "#outerArc" + d.i; }), 
     tspan = textPath.append('tspan'), // Inslide textPath, add a tspan element, for offset feature later. 
     path = d3.select(text.select('textPath').attr('xlink:href')); // Get the path to compute width of text later. 

    var startLoc = /M(.*?)A/; 
    var newStart = path.attr('d').match(startLoc)[1]; 
    var newEnd = path.attr('d').indexOf(' 0 0 0 ') > -1 
     ? path.attr('d').split(' 0 0 0 ')[1] 
     : path.attr('d').split(' 0 0 1 ')[1] ; 

    // Compute the start/end coordinate points of the arc that the text will follow. 
    var x1 = parseFloat(newStart.split(' ')[0]), 
     y1 = parseFloat(newStart.split(' ')[1]), 
     x2 = parseFloat(newEnd.split(' ')[0]), 
     y2 = parseFloat(newEnd.split(' ')[1]); 

    // Compute the length of the segment between the arc start/end points. This will be the 
    // width which the labels should wrap when reaching it. 
    var width = Math.sqrt(Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2)); 

    // And then we go on (with slight changes) with the example from Mike Bostock 
    // from here https://bl.ocks.org/mbostock/7555321 
    while (letter = letters.pop()) { 
     line.push(letter); 
     tspan.text(line.join("")); 
     if (tspan.node().getComputedTextLength() > width) { 
     line.pop(); 
     tspan.text(line.join("")); 
     line = [letter]; 

     // Instead of adding only a tspan element, add a new textPath so that the wrapped 
     // letters will be aligned to center. Without it, the letters will start drawing 
     // from right with part of them invisible, like if the labels are not wrapped. 
     textPath = text.append("textPath") 
      .attr("startOffset", '50%') 
      .style("text-anchor", "middle") 
      .attr("xlink:href", function(d) { return "#outerArc" + d.i; }), 

     // Add a tspan element to offset the wrapped letters from the previous line 
     tspan = textPath.append("tspan") 
      .attr('dy', '1em') 
      .attr('text-anchor', 'middle') 
      .text(letter); 
     } 
    } 
    }); 
} 

Am Ende war es eine interessante Herausforderung . Here ist eine Verzweigung Ihres Codepen mit einem Arbeitsbeispiel (die Änderungen beginnen mit Zeile 749).

Der Codepen hat nur die äußeren Etiketten umwickelt. Ich habe die inneren Etiketten für Sie gelassen, um den hier beschriebenen Ansatz zu implementieren. Viel Glück damit!

+0

danke, du hast mir sehr geholfen – bumbeishvili

Verwandte Themen