score:2

the reason you are seeing everything squished at the top-left corner is because all attributes are either nan or undefined. this is because you are using

.projection(function(d) { return [d.y, d.x / 180 * math.pi]; });

and

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

which is accessing d.x and d.y, which are undefined.

ideally, d.x and d.y are generated by the layout algorithms like d3.layout.tree(). however, in the code you provided, the data that you are passing into the tree-layout algorithm is incorrect.

d3.tree.layout() expects a hierarchical data structure, whereas you are providing it links and nodes, which will not work without some major workaround. if you want to use tree-layout, i suggest you convert your data into a hierarchical structure and then visualize it. here is an example of doing that

var width = window.innerwidth;
var height = window.innerheight;

var root = {
 "name": "1",
 "children": [
  {"name": "2"}
 ]
};

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

var tree = d3.layout.tree()
          .size([width, height-40]);

var nodes = tree.nodes(root);
var links = tree.links(nodes);

var path = d3.svg.line()
    .x(function(d) { return d.x; })
    .y(function(d) { return d.y;  });

  var link = svg.selectall(".link")
      .data(links)
      .enter()
      .append("path")
      .attr("class", "link")
      .attr("stroke", "black")
      .attr("stroke-width", 2);
      .attr("d", function(d){
        return path([d.source, d.target])
      });

  var node = svg.selectall(".node")
      .data(nodes)
      .enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) {
        return "translate(" + d.x + "," + (d.y + 20) + ")";       })

  node.append("circle")
      .attr("r", 4.5);

  node.append("text")
      .text(function(d) { return d.name; });

if however, you want to stick with the current data format:

var nodes = [{"id":"1","name":"a"},{"id":"2","name":"b"}];
var links = [{"source":0,"target":1}];

you should use force-directed layout.

here is an example of using force-directed layout with the data structure you have (http://jsfiddle.net/ankit89/3kl11j6j/)

var graph = {
 "nodes": [
     {"name": "leo"},
     {"name": "mike"},
     {"name": "raph"},
     {"name": "don"},
     {"name": "splinter"}
],
"links": [
    {"source": 0, "target": 4, "relation": "son"},
    {"source": 1, "target": 4, "relation": "son"},
    {"source": 2, "target": 4, "relation": "son"},
    {"source": 3, "target": 4, "relation": "son"}
]}


var force = d3.layout.force()
    .nodes(graph.nodes)
    .links(graph.links)
    .size([400, 400])
    .linkdistance(120)
    .charge(-30)
    .start();


 var svg = d3.select("svg");

var link = svg.selectall("line")
.data(graph.links)
.enter().append("line")
.style("stroke", "black");

var node = svg.selectall("circle")
.data(graph.nodes)
.enter().append("circle")
.attr("r", 20)
.style("fill", "grey")
.call(force.drag);

node.append("title")
.text(function(d) { return d.name; });

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; });

    node.attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; });
})

and finally, you do not necessarily need d3 layouts, you can even use your custom layout like this

http://jsfiddle.net/ankit89/uts5orrd/5/

var graph = {
 "nodes": [
     {"name": "leo", "level": 1},
     {"name": "mike", "level": 1},
     {"name": "raph", "level": 1},
     {"name": "don", "level": 1},
     {"name": "splinter", "level": 2}
],
"links": [
    {"source": 0, "target": 4, "relation": "son"},
    {"source": 1, "target": 4, "relation": "son"},
    {"source": 2, "target": 4, "relation": "son"},
    {"source": 3, "target": 4, "relation": "son"}
]}

 var svg = d3.select("svg");

svg.selectall("circle")
.data(graph.nodes)
.enter()
.append("circle")
.attr({
    "cx": function(d, i){
        var x;
        if(d.level == 1){
            x = i*100 + 100;
        }else{
            x = 250;
        }
        d.x = x;
        return x;
     },
    "cy": function(d, i){
            var y;
            if(d.level == 1){
                y = 260;
            }else{
                y = 60;
            }

            d.y = y;
            return y;
        },
    "r" : 30,
    "fill": "gray",
    "opacity": .5
})

svg.selectall("text")
.data(graph.nodes)
.enter()
.append("text")
.attr({
    "x": function(d){return d.x},
    "y": function(d){return d.y},
    fill: "steelblue"
})
.text(function(d){
    return d.name;
})


svg.selectall("line")
.data(graph.links)
.enter()
.append("line")
.attr({
    "x1": sourcex,
    "y1": sourcey,
    "x2": targetx,
    "y2": targety,
    "stroke-width": 2,
    "stroke": "grey"
})

function sourcex(d, i){
    var t = graph.nodes[d.source].x;
    return t;
}

function sourcey(d, i){
    var t = graph.nodes[d.source].y;
    return t;
}

function targetx(d, i){
    var t = graph.nodes[d.target].x;
    return t;
}

function targety(d, i){
    var t = graph.nodes[d.target].y;
    return t;
}
//console.log(graph.nodes)

here is the gist of the story:

  1. if using d3 layout, make your data structure match the data-structure expected by the layout and d3 will compute the x and y coordinates for you.

  2. if using want a custom layout, write function to determine the x and y coordinates for nodes and the links.


Related Query

More Query from same tag