0

我需要用 d3.js 绘制一棵树,它有两个“根”,即“力导向”这个图的 json(很简单,只是一个试验)是:

{
"nodes":
[
    {"name":"node1",
    "children":[
        {"name":"node2", "children":[{"name":"node3"}, {"name":"node4"}]},
        {"name":"node5", "children":[{"name":"node6", "children":[{"name":"node8"}]}, {"name":"node7"}]}
    ]},
    {"name":"node9",
    "children":[
        {"name":"node2", "children":[]}
    ]}
]

}

我尝试使用强制布局,但它似乎不起作用。所以我想也许我为我的目标使用了错误的布局,但我不知道应该使用哪种布局。我的代码是:

var width = 1200,
height = 800,
graph;

var force = d3.layout.force()
    .linkDistance(100)
    .charge(-120)
    .gravity(.05)
    .size([width, height])
    .on("tick", tick);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

svg.append("svg:defs").append("svg:marker")
        .attr("id", "arrowhead")
        .attr("viewBox", "0 -5 10 10")
        .attr("refX", 30)
        .attr("refY", -1.5)
        .attr("markerWidth", 6)
        .attr("markerHeight", 6)
        .attr("orient", "auto")
    .append("svg:path")
        .attr("d", "M0,-5L10,0L0,5");

var link = svg.selectAll(".link"),
node = svg.selectAll(".node");

d3.json("dirGraph.json", function(error, json) {
graph = json;
for(var i=0; i<graph.nodes.length; i++) 
    update(graph.nodes[i]);
})

function update(root) {

var nodes = flatten(root),
    links = d3.layout.tree().links(nodes);

force
    .nodes(nodes)
    .links(links)
    .start();

node = node.data(nodes, function(d){return d.id;});

node.exit().remove();

var nodeEnter = node.enter().append("svg:g")
    .attr("id", function(d){return d.id;})
    .attr("class", "node")
    .on("click", click)
    .call(force.drag);

nodeEnter.append("circle").attr("r", 20);

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

node.select("circle").style("fill", color);

link = link.data(links, function(d){return d.target.id;});

link.exit().remove();

link.enter().insert("line", ".node").attr("class", "link")
        .attr("x1", function(d){return d.source.x;})
        .attr("y1", function(d){return d.source.y;})
        .attr("x2", function(d){return d.target.x;})
        .attr("y2", function(d){return d.target.y;})
        .attr("marker-end", "url(#arrowhead)");

  }

  function tick() {

link.attr("d", function(d) {
    var dx = d.target.x - d.source.x,
    dy = d.target.y - d.source.y,
    dr = Math.sqrt(dx * dx + dy * dy);

    return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " +        d.target.x + "," + d.target.y;
});

link.attr("x1", function(d) { return d.source.x; })
  .attr("y1", function(d) { return d.source.y; })
  .attr("x2", function(d) { return d.target.x; })
  .attr("y2", function(d) { return d.target.y; });


node.attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")";
});

  }

  function color(d) {
    return d._children ? "#3182bd" // collapsed package
       : "#c6dbef"; // expanded package
  }

  function flatten(root) {

var nodes = [], i = 0;

function recurse(node) {
    if(node.children) node.children.forEach(recurse);
    if(!node.id) node.id = ++i;
    nodes.push(node);
}

recurse(root);

return nodes;

 }

 function click(d) {

if (d3.event.defaultPrevented) return; // ignore drag

if(d.children) {
    d._children = d.children;
    d.children = null;
} else {
    d.children = d._children;
    d._children = null;
}

update();

 }

我的问题是:我应该使用不同的布局还是应该以不同的方式使用强制布局?

4

0 回答 0