2012-06-13 12 views
13

I Text in einem Rechteck schreiben möchte ich wie folgt erstellen:Fit Text in SVG Element (mit D3/JS)

body = d3.select('body') 

svg = body.append('svg').attr('height', 600).attr('width', 200) 

     rect = svg.append('rect').transition().duration(500).attr('width', 150) 
         .attr('height', 100) 
         .attr('x', 40) 
         .attr('y', 100) 
         .style('fill', 'white') 
         .attr('stroke', 'black') 

     text = svg.append('text').text('This is some information about whatever') 
         .attr('x', 50) 
         .attr('y', 150) 
         .attr('fill', 'black')​ 

Doch wie Sie (http://jsfiddle.net/Tmj7g/3/) der Text wird abgeschnitten sehen. Irgendwelche raffinierten Möglichkeiten, einen Absatz innerhalb des erstellten Svg-Rechtecks ​​zu schreiben? Danke,

Antwort

16

Die Antwort auf this question könnte relevant sein. SVG bietet keine Möglichkeit, Text automatisch zu umbrechen, aber Sie können HTML in SVGs einbetten und dann beispielsweise div verwenden.

Ich habe die jsfiddle here aktualisiert, aber es funktioniert nicht so gut zusammen mit der Animation. Wenn Sie sicherstellen möchten, dass es ordnungsgemäß funktioniert und sich wie jedes andere SVG-Element verhält, müssen Sie die Zeilenumbrüche vorberechnen und manuell einfügen.

+0

Funktioniert das auf IE9? Wenn ja, was sind die Alternativen? Ich weiß, dass das vor langer Zeit beantwortet wurde. – Jose

+0

Ich habe dies in IE9 nicht versucht. –

+0

Ja, es funktioniert überhaupt nicht in IE9, da es keine Fremdobjekte unterstützt. Gibt es Alternativen zum Umbrechen von Text in D3.js? – Jose

15

Um es mit den Animationen arbeiten zu lassen, schließen Sie einfach ein Gruppenelement ein und animieren Sie dieses stattdessen. http://jsfiddle.net/MJJEc/

body = d3.select('body') 
svg = body.append('svg') 
        .attr('height', 600) 
        .attr('width', 200); 
    var g = svg.append('g').attr("transform" ,"scale(0)"); 
    rect = g.append('rect') 
        .attr('width', 150) 
        .attr('height', 100) 
        .attr('x', 40) 
        .attr('y', 100) 
        .style('fill', 'none') 
        .attr('stroke', 'black') 
    text = g.append('foreignObject') 
        .attr('x', 50) 
        .attr('y', 130) 
        .attr('width', 150) 
        .attr('height', 100) 
        .append("xhtml:body") 
        .html('<div style="width: 150px;">This is some information about whatever</div>') 

    g.transition().duration(500).attr("transform" ,"scale(1)"); 
3

könnte diese Technik nützlich sein. Es funktioniert mit der aktuellen svg spec und ohne foreign Element http://bl.ocks.org/mbostock/7555321

+0

Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz zur Verfügung zu stellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert – Ian

2

Ich hatte ein ähnliches Problem und fand eine vernünftige Lösung, die durch die Breite meiner Box zu berechnen. Zweitens habe ich herausgefunden, dass im Durchschnitt die Zeichenbreite für meine aktuelle Schriftart ist etwa 8. Als nächstes mache ich einfach eine Teilzeichenfolge auf den Text angezeigt werden. Das scheint in den meisten Fällen perfekt zu funktionieren.

var rectText = rectangles.append("text") 
    .text(function(d) { 

     TextBoxLength = timeScale(dateFormat.parse(d.endTime)) - timeScale(dateFormat.parse(d.startTime)); 
     return d.task.substring(0, Math.floor(TextBoxLength/8)); 
    }) 
    .attr("x", function(d) { 
     return (timeScale(dateFormat.parse(d.endTime)) - timeScale(dateFormat.parse(d.startTime)))/2 + timeScale(dateFormat.parse(d.startTime)) + theSidePad; 
    }) 
    .attr("y", function(d, i) { 
     return d.position * theGap + 14 + theTopPad; 
    }) 
    .attr("font-size", 12) 
    .attr("text-anchor", "middle") 
    .attr("text-height", theBarHeight) 
    .attr("fill", "#000000"); 
2

Ein anderer Ansatz, wenn eine gerade Linie von Text in ein svg Element zu passen versucht, könnte die Strategie in http://bl.ocks.org/mbostock/1846692 gefunden verwenden:

node.append("text") 
    .text(function(d) { return d.name; }) 
    .style("font-size", function(d) { return Math.min(2 * d.r, (2 * d.r - 8)/this.getComputedTextLength() * 24) + "px"; }) 
    .attr("dy", ".35em");