0

I'm testinf d3.js and i'm trying to add links between a root node (the center one in the JsFiddle) and child nodes. How can i achieve that simply ?

Here is the code that i have so far: http://jsfiddle.net/fLqekg12/2/

var container = d3.select("svg#svg");
var data = [2, 1, 1, 1, 1, 1, 1];

var dataTree = {
    id: "root",
    size: 12,
    children: data.map(function (d) {
        return {
            size: 10,
            parent: "root"
        };
    })
};

var maxRadius = 50,
    padding = 40;

var radiusScale = d3.scale.sqrt()
    .domain([0, 50 /* d3.max(data) */ ])
    .range([0, 50]); // maxRadius

var roughCircumference = d3.sum(data.map(radiusScale)) * 2 + padding * (data.length - 1),
    radius = roughCircumference / (Math.PI * 2);

// make a radial tree layouts
var tree = d3.layout.tree()
    .size([360, radius])
    .separation(function (a, b) {
    return radiusScale(a.size) + radiusScale(b.size);
});

// create a holder group for all the graph nodes
var svgGroup = container.append('g')
    .attr('transform', 'translate(' + 80 + ',' + 90 + ')');


var nodes = tree.nodes(dataTree),
    links = tree.links(nodes); // and then... ?

// declare the nodes (this creates placed groups)
var svgNodes = svgGroup.selectAll('.node')
    .data(nodes) // cut out the root node, we don't need it : nodes.slice(1)
.enter().append('g')
    .attr('class', 'node')
    .attr('transform', function (d) {
    return "rotate(" + (d.x - 90) + ") translate(" + d.y + ")";
});

// append a cirl to all nodes groups
svgNodes.append('circle').attr('r', function (d) {
    return d.size;
});

EDIT

Progress was made with this code.

var diagonal = d3.svg.diagonal.radial()
        .projection(function (d) {
        return [d.y, d.x / 180 * Math.PI];
    });

var svgLinks = svgGroup.selectAll('path')
        .data(tree.links(nodes))
        .enter().append('svg:path')
        .attr('class', 'link')
        .attr('d', diagonal)
        .attr("fill", "none")
        .attr("stroke", "gray");

Fiddle update: http://jsfiddle.net/fLqekg12/4/ The only thing i need now is straight lines instead of curved ones. Anyone ?

Romain Bruckert
  • 2,546
  • 31
  • 50
  • You create "nodes" then create element having node as class. You have to do the same with "links" : create svg:line element using coordinate of source and target. – Matthieu May 18 '15 at 13:32
  • Thanks @Matthieu , i'm aware of that and understand the general principle but i'm not confortable enough with d3 js to write the actual the code and make it work (i've been trying from several examples already); – Romain Bruckert May 18 '15 at 13:39
  • Maybe you can use directly force layout : https://github.com/mbostock/d3/wiki/Force-Layout or look at d3js svg line function – Matthieu May 18 '15 at 13:48
  • I could, but won't ;-) . I wish to do it from my code for learning purposes. – Romain Bruckert May 18 '15 at 13:57

2 Answers2

0

After compute and create your nodes, you have to create your links as svg line element:

var link = svgGroup.selectAll('line.link')
    .data(links)
    .enter().append('svg:line')
        .attr("class", "link")
        .attr("style","stroke:black")
        .attr("x1", function(d) { return ... (x coordinate source node) })
        .attr("y1", function(d) { return ... (y coordinate source node) })
        .attr("x2", function(d) { return ... (x coordinate target node) })
        .attr("y2", function(d) { return ... (y coordinate target node) });

You juste have to find the good formula to compute position from x,y polar coordinate.

Matthieu
  • 221
  • 1
  • 11
  • And do you know how to retrieve source/target coordinates ? – Romain Bruckert May 18 '15 at 14:22
  • They are store in d.source(.x/y) and d.target(.x/y) – Matthieu May 18 '15 at 14:24
  • Actually its not data(nodes) but data(links). And the lines are not drawn with the correct coordinates (see http://jsfiddle.net/fLqekg12/3 ). I think its because - if you read my code - the nodes are transformed. So their x/y position are still what they are but transform gives them another position. What do you think ? – Romain Bruckert May 18 '15 at 14:27
  • Yeah, my fault : it's data(links). And you have to transform links position like you do for nodes (with rotation on x and distance on y) – Matthieu May 18 '15 at 14:32
  • Not really working or what i was looking for but it pointed me to the right direction. – Romain Bruckert May 18 '15 at 15:27
0

The two working solutions are:

Using paths (easiest one, but could not transform curves into straight lines) : http://jsfiddle.net/fLqekg12/4/

Using lines. The trick is that lines cannot be used directly in place of path (see why here) and if you transform nodes, it does not work.

The solution i found was found from this post: lines have to be transformed as well if your nodes are transformed:

Use d.target.x / 180 * Math.PI)on y1 and y2 because i want a radial projection and finally transform the lines again with :

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

Full working example here: http://jsfiddle.net/fLqekg12/6/

Community
  • 1
  • 1
Romain Bruckert
  • 2,546
  • 31
  • 50