change SVG text to css word wrapping

后端 未结 4 755
星月不相逢
星月不相逢 2020-12-10 13:35

The following code is used to show the text labels of a javascript tree diagram.

nodeEnter.append(\"svg:text\")
        .attr(\"x\", function(d) { return d._         


        
相关标签:
4条回答
  • 2020-12-10 13:48

    foreignObject isn't supported by IE and Chrome doesn't support transitions on it. If those limitations are okay then I recommend using foreignObject because you get all of the formatting of HTML+CSS.

    If you need to support IE or transitions then I suggest using a D3 plugin such as D3plus. It makes text wrapping very easy.

    d3plus.textwrap()
      .container('selector')
      .draw();
    

    Checkout the docs to read about all of its features.

    0 讨论(0)
  • 2020-12-10 13:58

    This is a sample code to word-wrap texts with D3:

    var nodes = [
        {title: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut"}
    ]
    
    var w = 960, h = 800;
    
    var svg = d3.select("body").append("svg")
        .attr("width", w)
        .attr("height", h);
    
    var vSeparation = 13, textX=200, textY=100, maxLength=20
    
    var textHolder = svg.selectAll("text")
        .data(nodes)
        .enter().append("text")
        .attr("x",textX)
        .attr("y",textY)
        .attr("text-anchor", "middle")
        .each(function (d) {
            var lines = wordwrap(d.title, maxLength)
    
            for (var i = 0; i < lines.length; i++) {
                d3.select(this).append("tspan").attr("dy",vSeparation).attr("x",textX).text(lines[i])
            }
        });
    
    
    function wordwrap(text, max) {
        var regex = new RegExp(".{0,"+max+"}(?:\\s|$)","g");
        var lines = []
    
        var line
        while ((line = regex.exec(text))!="") {
            lines.push(line);
        } 
    
        return lines
    }
    
    0 讨论(0)
  • 2020-12-10 14:02

    You can use this generic function using D3.js to wrap text in an svg:text element into multiple svg:tspan children (one tspan per line):

        function wrapText(text, width) {
            text.each(function () {
                var textEl = d3.select(this),
                    words = textEl.text().split(/\s+/).reverse(),
                    word,
                    line = [],
                    linenumber = 0,
                    lineHeight = 1.1, // ems
                    y = textEl.attr('y'),
                    dx = parseFloat(textEl.attr('dx') || 0), 
                    dy = parseFloat(textEl.attr('dy') || 0),
                    tspan = textEl.text(null).append('tspan').attr('x', 0).attr('y', y).attr('dy', dy + 'em');
    
                while (word = words.pop()) {
                    line.push(word);
                    tspan.text(line.join(' '));
                    if (tspan.node().getComputedTextLength() > width) {
                        line.pop();
                        tspan.text(line.join(' '));
                        line = [word];
                        tspan = textEl.append('tspan').attr('x', 0).attr('y', y).attr('dx', dx).attr('dy', ++linenumber * lineHeight + dy + 'em').text(word);
                    }
                }
            });
        }
    

    You can use it like this:

    svg.selectAll('text').call(wrapText, 100);
    
    0 讨论(0)
  • 2020-12-10 14:05

    You probably want to use the SVG foreignObject tag, so you would have something like this:

    nodeEnter.append("foreignObject")
        .attr("x", function(d) { return d._children ? -8 : -48; }) /*the position of the text (left to right)*/
        .attr("y", 3) /*the position of the text (Up and Down)*/
        .attr("width", your_text_width_variable)
        .attr("height", your_text_height_variable)
        .append("xhtml:body")
        .append("p")
        .text(function(d) { return d.name; });
    

    Here is a gist by Mike Bostock which helped me: https://gist.github.com/1424037

    0 讨论(0)
提交回复
热议问题