This is supposed to be an answer to this question.
It combines this example with the use of invisible nodes.
This is supposed to be an answer to this question.
It combines this example with the use of invisible nodes.
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
.link { | |
stroke: black; | |
stroke-width: 2px; | |
} | |
.node { | |
stroke: white; | |
stroke-width: 2px; | |
} | |
</style> | |
<body> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<script> | |
var width = 960, height = 500, colors = d3.scale.category10(); | |
var n = 200, | |
k = 7, | |
nodes = d3.range(n).map(function (num) { return {type: num % k, charge: -50} }), | |
links = d3.range(1,n).map(function (a) { return {source: nodes[0], target: nodes[a]} }); | |
nodes[0].fixed = true; | |
nodes[0].x = 480; | |
nodes[0].y = 250; | |
var invisibleNodes = d3.range(k).map(function () { return {charge: -1000} }), | |
invisibleLinks = invisibleNodes.map(function (a) { return {source: 0, target: a} }); | |
var force = d3.layout.force() | |
.size([width, height]) | |
.nodes(nodes.concat(invisibleNodes)) | |
.links(invisibleLinks) | |
.charge(function (d) { return d.charge }) | |
.on("tick", tick) | |
.start(); | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height); | |
svgLinks = svg.selectAll(".link").data(links) | |
.enter().append("line") | |
.attr("class", "link") | |
svgNodes = svg.selectAll(".node").data(nodes) | |
.enter().append("circle") | |
.attr("class", "node") | |
.attr("r", 8) | |
.style("fill", function (d) { return colors(d.type) }) | |
.call(force.drag); | |
function tick(e) { | |
var k = .3 * e.alpha; | |
// Push nodes toward their designated focus. | |
nodes.forEach(function(o, i) { | |
o.y += (invisibleNodes[o.type].y - o.y) * k; | |
o.x += (invisibleNodes[o.type].x - o.x) * k; | |
}); | |
svgNodes | |
.attr("cx", function(d) { return d.x }) | |
.attr("cy", function(d) { return d.y }); | |
svgLinks | |
.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 }); | |
}; | |
</script> |