2014-01-15 104 views
2

尝试获取D3中的树布局以使子节点与子节点更接近。这里是代码:D3树布局 - 有孩子的子节点之间的距离

var margin = { 
      top: 20, 
      right: 120, 
      bottom: 20, 
      left: 120 
    }, 
    width = 960 - margin.right - margin.left, 
    height = 800 - margin.top - margin.bottom; 

    var i = 0, 
      duration = 750, 
      rectW = 185, 
      rectH = 45; 

    var tree = d3.layout.tree() 
     .nodeSize([200, 40]); 

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

    var svg = d3.select("#body").append("svg").attr("width", 1000).attr("height", 1000) 
     .call(zm = d3.behavior.zoom().scaleExtent([0,1]).on("zoom", redraw)) 
     .append("g") 
     .attr("transform", "translate(" + 30 + "," + 20 + ")"); 

    //necessary so that zoom knows where to zoom and unzoom from 
    zm.translate([350, 20]); 

    root.x0 = width/2; 
    root.y0 = 0; 

    update(root); 

    d3.select("#body").style("height", "800px"); 

    function update(source) { 

     // Compute the new tree layout. 
     var nodes = tree.nodes(root).reverse(), 
      links = tree.links(nodes); 


     // Normalize for fixed-depth. 
     nodes.forEach(function (d) { 
      d.y = (d.depth * 120); 
     }); 

     // 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.x0 + "," + source.y0 + ")"; 
      }) 
      .on("click", click); 

     // Add rectangles to nodes 
     nodeEnter.append("rect") 
      .attr("width", function (d) {     
       return rectW; 
       //return d._children ? "lightsteelblue" : "#fff"; 
      }) 
      .attr("height", rectH) 
      .attr("class", function (d) { 
       return "rect-" + d.state; 
      }); 

     // Add text to nodes 
     nodeEnter.append("text") 
      .attr("x", rectW/2) 
      .attr("y", rectH/2) 
      .attr("dy", ".35em") 
      .attr("text-anchor", "middle") 
      .text(function (d) { 
       return d.name; 
      }); 

     // Transition nodes to their new position. 
     var nodeUpdate = node.transition() 
      .duration(duration) 
      .attr("transform", function (d) { 
       return "translate(" + d.x + "," + d.y + ")"; 
      }); 

     nodeUpdate.select("rect") 
      .attr("width", rectW) 
      .attr("height", rectH) 
      .attr("class", function (d) { 
       return "rect-" + d.state; 
      }); 

     nodeUpdate.select("text") 
      .style("fill-opacity", 1); 

     // 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", function (d) { 
       return "link " + d.target.dest; 
      }) 
      .attr("x", rectW/2) 
      .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(); 


     // Update the link labels… 
     var linkLabel = svg.selectAll("text.link-label") 
      .data(links, function (d) { 
       return d.target.id; 
      }); 

     // Enter any new links at the parent's previous position. 
     linkLabel.enter().insert("text", "path") 
      .text(function (d) { 
       return (d.target.state !== "open") ? null : "If " + d.target.dest; 
      }) 
      .attr("class", function (d) { 
       return "link-label " + d.target.dest; 
      }) 
      .attr("x", function (d) { 
       return d.target.x + rectW/2; 
      }) 
      .attr("y", function (d) { 
       return d.target.y + rectH * 2 - 30; 
      })    
      .attr('text-anchor', 'middle') 
      .style("fill-opacity", 0);; 

     // Transition link labels 
     linkLabel.transition() 
      .delay(duration) 
      .style("fill-opacity", 1); 


     // Stash the old positions for transition. 
     nodes.forEach(function (d) { 
      d.x0 = d.x; 
      d.y0 = d.y; 
     }); 
    } 

    // Toggle children on click. 
    function click(d) { 
     return false; 
     if (d.children) { 
      d._children = d.children; 
      d.children = null; 
     } else { 
      d.children = d._children; 
      d._children = null; 
     } 
     update(d); 
    } 

    //Redraw for zoom 
    function redraw() { 
     //console.log("here", d3.event.translate, d3.event.scale); 
     svg.attr("transform", 
      "translate(" + d3.event.translate + ")" 
      + " scale(" + d3.event.scale + ")"); 
    } 

Here is a jsbin上面的代码。我想看到的是海军色的“节点1”和“节点2”靠得更近,同时保留了没有子节点(灰色节点)的节点之间的距离。

这是可能的,我该怎么做?

回答

6

我找到了答案。这是分离方法。这让我知道我在找什么:

tree.separation(function separation(a, b) { 
      return a.parent == b.parent ? 1 : 1.5; 
     });