2

我是 d3 的新手,我想知道是否可以让 svg 遵循树的层次结构。

假设我有一个这样的json:

{
       "name": "root",
       "children": [
           {
               "name" : "child1",
               "children": [
                   {
                       "name": "child1_1"
                   },
                   {
                       "name": "child1_2"
                   }
               ]
           },
           {
               "name": "child2",
               "children": [
                   {
                  "name": "child2_1"
                   },
                   {
                       "name": "child2_2"
                   }
               ]
           }   
        ]
}

我怎样才能有这样的 svg 结构:

<g class="root">
  <g class="child1">
    <g class="child1_1">
    </g>
    <g class="child1_2">
    </g>
  </g>
  <g class="child2">
    <g class="child2_1">
    </g>
    <g class="child2_2">
    </g>
  </g>
</g>

我试过这样的东西:

var w = 960,
    h = 2000,
    i = 0,
    root;

var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.y, d.x]; });

var vis = d3.select("#chart").append("svg:svg")
    .attr("width", w)
    .attr("height", h)
    .append("svg:g")
    .attr("transform", "translate(40,0)");

d3.json(
    './small_tree.json',
    function(json) {
        json.x0 = 800;
        json.y0 = 0;
        update(root = json);
    }
);
function update(source) {

    var nodes = tree.nodes(root);
    var child = vis.selectAll('g.child_node')
        .data(nodes,function(d){return d.children;})
        .enter()
        .append('g')
        .attr("class", "child_node");
}

我得到了根节点的子节点的标签,但我不知道如何递归地为子节点创建嵌套组。

有人有想法吗?

谢谢,

雷姆

4

1 回答 1

1

D3 本身并不处理递归,而且看起来标准的分层布局通常不会创建嵌套结构。相反,您需要在自己的代码中递归。这是一个实现:

// simple offset, just to make things visible
var offset = 0;

// recursion function
function addNode(selection, depth) {
   // set the current children as the data array
   var nodeGroup = selection.selectAll('g.child_node')
       .data(function(d) { return d.children })
     .enter()
       // add a node for each child
       .append('g')
       .attr("class", "child_node")
       // very simple depth-based placement
       .attr("transform", "translate(" + (depth * 30) + "," +
            (++offset * 15) + ")");

    nodeGroup.append("text")
       .attr("dy", "1em")
       .text(function(d) { return d.name });

    // recurse - there might be a way to ditch the conditional here
    nodeGroup.each(function(d) {
        if (d.children) nodeGroup.call(addNode, depth + 1);
    });
}

d3.json(
    './small_tree.json',
    function(root) {
        // kick off the recursive append
        vis
            .datum({ children: [root] })
            .call(addNode, 0);
    }
}

见小提琴:http: //jsfiddle.net/nrabinowitz/ELYWa/

于 2013-07-18T16:31:50.697 回答