【问题标题】:adding word wrap for D3.js tree chart labels为 D3.js 树形图标签添加自动换行
【发布时间】:2016-05-24 20:48:37
【问题描述】:

我是 D3.js 的新手,想在 tree chart 中包装长标签

谁能指导我如何做到这一点?

这是我尝试过的:

var insertLinebreaks = function (t, d, width) {
    var el = d3.select(t);
    var p = d3.select(t.parentNode);
    p.append("foreignObject")
        .attr('x', -width/2)
        .attr("width", width)
        .attr("height", 200)
      .append("xhtml:p")
        .attr('style','word-wrap: break-word; text-align:center;')
        .html(d);    

    el.remove();
};

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    svg.selectAll('text')
    .each(function(d,i){ insertLinebreaks(this, d, 10 ); });

【问题讨论】:

    标签: d3.js treechart


    【解决方案1】:

    我设法让它工作。 感谢this sample

    function wrap(text, width) {
      text.each(function() {
        var text = d3.select(this),
            words = text.text().split(/\s+/).reverse(),
            word,
            line = [],
            lineNumber = 0,
            lineHeight = 1.1, // ems
            y = text.attr("y"),
            dy = parseFloat(text.attr("dy"))/2,
            tspan = text.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 = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word);
          }
        }
      });
    }
    
    var json = 
    {
        "name": "Base",
        "children": [
            {
                "name": "I have a very long sentence that needs to be broken up",
                "children": [
                    {
                        "name": "Section 1",
                        "children": [
                            {"name": "Child 1"},
                            {"name": "Child 2"},
                            {"name": "Child 3"}
                        ]
                    },
                    {
                        "name": "Section 2",
                        "children": [
                            {"name": "Child 1"},
                            {"name": "Child 2"},
                            {"name": "Child 3"}
                        ]
                    }
                ]
            },
            {
                "name": "Either you break this up or one of us is in deep trouble",
                "children": [
                    {
                        "name": "Section 1",
                        "children": [
                            {"name": "Child 1"},
                            {"name": "Child 2"},
                            {"name": "Child 3"}
                        ]
                    },
                    {
                        "name": "Section 2",
                        "children": [
                            {"name": "Child 1"},
                            {"name": "Child 2"},
                            {"name": "Child 3"}
                        ]
                    }
                ]
            }
        ]
    };
    
    var width = 700;
    var height = 650;
    var maxLabel = 150;
    var duration = 500;
    var radius = 5;
    
    var i = 0;
    var root;
    
    var tree = d3.layout.tree()
        .size([height, width]);
    
    var diagonal = d3.svg.diagonal()
        .projection(function(d) { return [d.y, d.x]; });
    
    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height)
            .append("g")
            .attr("transform", "translate(" + maxLabel + ",0)");
    
    root = json;
    root.x0 = height / 2;
    root.y0 = 0;
    
    root.children.forEach(collapse);
    
    function update(source) 
    {
        // Compute the new tree layout.
        var nodes = tree.nodes(root).reverse();
        var links = tree.links(nodes);
    
        // Normalize for fixed-depth.
        nodes.forEach(function(d) { d.y = d.depth * maxLabel; });
    
        // Update the nodes…
        var node = svg.selectAll("g.node")
            .data(nodes, function(d){ 
                return d.id || (d.id = ++i); 
            });
    
        // Enter any new nodes at the parent's previous position.
        var nodeEnter = node.enter()
            .append("g")
            .attr("class", "node")
            .attr("transform", function(d){ return "translate(" + source.y0 + "," + source.x0 + ")"; })
            .on("click", click);
    
        nodeEnter.append("circle")
            .attr("r", 0)
            .style("fill", function(d){ 
                return d._children ? "lightsteelblue" : "white"; 
            });
    
        nodeEnter.append("text")
            .attr("x", function(d){ 
                var spacing = computeRadius(d) + 5;
                return d.children || d._children ? -spacing : spacing; 
            })
            .attr("dy", "3")
            .attr("text-anchor", function(d){ return d.children || d._children ? "end" : "start"; })
            .text(function(d){ return d.name; })
            .style("fill-opacity", 0);
    
        // Transition nodes to their new position.
        var nodeUpdate = node.transition()
            .duration(duration)
            .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
    
        nodeUpdate.select("circle")
            .attr("r", function(d){ return computeRadius(d); })
            .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
    
        nodeUpdate.select("text").style("fill-opacity", 1);
        nodeUpdate.select("text").call(wrap, 200); // <++++++++++ wrap it!
        // Transition exiting nodes to the parent's new position.
        var nodeExit = node.exit().transition()
            .duration(duration)
            .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
            .remove();
    
        nodeExit.select("circle").attr("r", 0);
        nodeExit.select("text").style("fill-opacity", 0);
    
        // Update the links…
        var link = svg.selectAll("path.link")
            .data(links, function(d){ return d.target.id; });
    
        // Enter any new links at the parent's previous position.
        link.enter().insert("path", "g")
            .attr("class", "link")
            .attr("d", function(d){
                var o = {x: source.x0, y: source.y0};
                return diagonal({source: o, target: o});
            });
    
        // Transition links to their new position.
        link.transition()
            .duration(duration)
            .attr("d", diagonal);
    
        // Transition exiting nodes to the parent's new position.
        link.exit().transition()
            .duration(duration)
            .attr("d", function(d){
                var o = {x: source.x, y: source.y};
                return diagonal({source: o, target: o});
            })
            .remove();
    
        // Stash the old positions for transition.
        nodes.forEach(function(d){
            d.x0 = d.x;
            d.y0 = d.y;
        });
    }
    
    function computeRadius(d)
    {
        if(d.children || d._children) return radius + (radius * nbEndNodes(d) / 10);
        else return radius;
    }
    
    function nbEndNodes(n)
    {
        nb = 0;    
        if(n.children){
            n.children.forEach(function(c){ 
                nb += nbEndNodes(c); 
            });
        }
        else if(n._children){
            n._children.forEach(function(c){ 
                nb += nbEndNodes(c); 
            });
        }
        else nb++;
    
        return nb;
    }
    
    function click(d)
    {
        if (d.children){
            d._children = d.children;
            d.children = null;
        } 
        else{
            d.children = d._children;
            d._children = null;
        }
        update(d);
    }
    
    function collapse(d){
        if (d.children){
            d._children = d.children;
            d._children.forEach(collapse);
            d.children = null;
        }
    }
    
    update(root);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多