Take a look at this example.
This is your example, but a little bit modified. The basic idea is to do forced layout in two passes:
- first will allow a little bit more relaxed way of layout: nodes will be allowed to deviate from their "level"; this will allow spontaneous jumping one over another to achieve better link layout (less intersection)
- second will "return" nodes to their respective level
Key portions of the code:
Custom force:
graph.nodes.forEach(function(o, i) {
o.y += (y(o.level) - o.y) * k;
});
Layout definition:
var force = d3.layout.force()
.charge(-1000)
.gravity(0.2)
.linkDistance(30)
.size([width, height])
Calling force.start() two times:
force
.nodes(graph.nodes)
.links(graph.links)
.on("tick", tick)
.start();
setTimeout(function() {
first = 0;
force.start();
}, 6000);
Variable "first":
var first = 1;
if(first) {
var k = e.alpha;
}
else{
var k = 10 * e.alpha;
}
Screenshot after first pass:
After second pass:
I'll try to improve the example, this is a little bit "dirty" development prototype, but I don't have time right now, maybe tomorrow.
EDIT: NOTE: I just noticed that actually the data is constant, and, however, the layout differs from simulation to simulation. This doesn't have to be that way. It can be much more deterministic. I'll try to fix that too tomorrow. I'll also do better chaining layouts with "end" event.