javascript - Space out nodes evenly around root node in D3 force layout -


i starting on d3, if has general suggestions on thing might not doing correctly/optimally, please let me know :)

i trying create force directed graph nodes spaced out evenly (or close enough) around center root node (noted larger size).

here's example of layout i'm trying achieve (i understand won't same every time):
enter image description here

i have following graph:

var width = $("#thevizness").width(),     height = $("#thevizness").height();  var color = d3.scale.ordinal().range(["#ff0000", "#fff000", "#ff4900"]);  var force = d3.layout.force()     .charge(-120)     .linkdistance(30)     .size([width, height]);  var svg = d3.select("#thevizness").append("svg")     .attr("width", width)     .attr("height", height);  var loading = svg.append("text")     .attr("class", "loading")     .attr("x", width / 2)     .attr("y", height / 2)     .attr("dy", ".35em")     .style("text-anchor", "middle")     .text("loading...");  /* forcedirectdata.json {     "nodes":[       {"name":"file1.exe","colorgroup":0},       {"name":"file2.exe","colorgroup":0},       {"name":"file3.exe","colorgroup":0},       {"name":"file4.exe","colorgroup":0},       {"name":"file5.exe","colorgroup":0},       {"name":"file6.exe","colorgroup":0},       {"name":"file7.exe","colorgroup":0},       {"name":"file8.exe","colorgroup":0},       {"name":"file8.exe","colorgroup":0},       {"name":"file9.exe","colorgroup":0}     ],     "links":[       {"source":1,"target":0,"value":10},       {"source":2,"target":0,"value":35},       {"source":3,"target":0,"value":50},       {"source":4,"target":0,"value":50},       {"source":5,"target":0,"value":65},       {"source":6,"target":0,"value":65},       {"source":7,"target":0,"value":81},       {"source":8,"target":0,"value":98},       {"source":9,"target":0,"value":100}     ] } */  d3.json("https://dl.dropboxusercontent.com/u/5772230/forcedirectdata.json", function (error, json) {     var nodes = json.nodes;     force.nodes(nodes)         .links(json.links)         .linkdistance(function (d) {             return d.value * 1.5;         })         .charge(function(d){             var charge = -500;              if (d.index === 0) charge = 0;              return charge;         })         .friction(0.4);      var link = svg.selectall(".link")         .data(json.links)         .enter().append("line")         .attr("class", "link")                       .style("stroke-width", 1);          var files = svg.selectall(".file")         .data(json.nodes)         .enter().append("circle")         .attr("class", "file")         .attr("r", 10)         .attr("fill", function (d) {             return color(d.colorgroup);         });     var totalnodes = files[0].length;      files.append("title")         .text(function (d) { return d.name; });      force.start();     (var = totalnodes * totalnodes; > 0; --i) force.tick();       nodes[0].x = width / 2;     nodes[0].y = height / 2;      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; });      files.attr("cx", function (d) { return d.x; })         .attr("cy", function (d) { return d.y; })         .attr("class", function(d){             var classstring = "file"              if (d.index === 0) classstring += " rootfile";              return classstring;         })         .attr("r", function(d){             var radius = 10;              if (d.index === 0) radius = radius * 2;              return radius;         });     force.on("tick", function() {     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; });      files.attr("cx", function(d) { return d.x; })         .attr("cy", function(d) { return d.y; });   });      loading.remove();    });  

jsfiddle

i have tried getting close charge() method. thought giving every node besides root node higher charge accomplish this, did not.

what can have child nodes evenly spaced around root node?

yes, force layout perfect tool situations yours.

you need change little initialization of layout, this

force.nodes(nodes)     .links(json.links)     .charge(function(d){         var charge = -500;         if (d.index === 0) charge = 10 * charge;         return charge;     }); 

and voila

enter image description here

explanation. had remove settings friction , linkdistance since affected placement in bad way. charge root node 10 times larger other nodes dominantly pushed away root. other nodes repel each other, , perfect symmetry achieved @ end, result.

jsfiddle here.


i see code attempted affect distance root node , other nodes utilizing linkdistance dependant on data. however, might better (although counter-intuitive) use linkstrength purpose, this

force.nodes(nodes)     .links(json.links)     .linkstrength(function (d) {         return d.value / 100.0;     })     .charge(function(d){         var charge = -500;         if (d.index === 0) charge = 10 * charge;         return charge;     }); 

but need experiment.


for centering , fixing root node, can use this

nodes[0].fixed = true; nodes[0].x = width / 2; nodes[0].y = height / 2; 

but before initialization of layout, in this jsfiddle.


Comments

Popular posts from this blog

css - SVG using textPath a symbol not rendering in Firefox -

Java 8 + Maven Javadoc plugin: Error fetching URL -

node.js - How to abort query on demand using Neo4j drivers -