我需要绘制一个带有两个“根”的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();
}
我的问题是:我应该使用不同的布局还是应该以不同的方式使用力布局?