Mupparthy Ravindranath - 8 days ago 5
Javascript Question

# d3js radial tidy tree - how are dx and dy populated?

I am a beginner to d3js, playing around to get a very simple radial tidy tree to work.

I have written the following piece of code to generate a tree.

``````139 function radialTree(window, svg, data) {
140  debugger;
141   console.log("Will build radial tree here...");
143   console.log("tree data:", result);
144
145   g = svg.append("g").attr("transform", "translate(" + (w / 2 + 40) + "," + (h / 2 + 90) + ")");
146
147   var stratify = d3.stratify()
148             .parentId(function(d) { return d.parent;});
149   var tree = d3.tree()
150               .size([360, 500])
151               .separation(function(a,b) { return (a.parent == b.parent?1:2)/a.depth; });
152   var root = d3.hierarchy(result);
153
155               .data(root.descendants().slice(1))
156               .enter().append('path')
158               .attr('d', function(d) {
159                 debugger;
160                 return "M" + project(d.x, d.y)
161                       + "C" + project(d.x, (d.y + d.parent.y)/2)
162                       + " " + project(d.parent.x, (d.y + d.parent.y)/2)
163                       + " " + project(d.parent.x, d.parent.y)
164               });
165
166   var node = g.selectAll(".node")
167               .data(root.descendants())
168               .enter().append('g')
169               .attr('class', function(d) { return "node" + (d.children?" node--internal":" node--leaf"); })
170               .attr('transform', function(d) { return "translate(" + project(d.x, d.y) + ")"; })
171
172   node.append('circle').attr('r', 2.5);
173   node.append('text')
174      .attr('dy', '.31em')
175      .attr('x', function(d) { return d.x < 180 === !d.children ? 6: -6; })
176      .style('text-anchor', function(d) { return d.x < 180 === !d.children ? "start":"end"; })
177      .attr('transform', function(d) { return "rotate(" + (d.x<180? d.x-90 : d.x+90) + ")"; })
178      .text(function(d) { return d.name; });
179
180   return svg;
181 }
182
183 function project(x, y) {
184   var angle = (x-90)/180 * Math.PI,  radius = y;
186 }
187
``````

Since, I have the tree data in a form that is generated by stratify (i guess so), I am not calling the stratify() function explicitly. The json data fed to the tree function is as below:

``````tree data: { parent: null,
name: 'root',
id: 'root',
status: 'green',
depth: 0,
children:
[ { parent: 'root',
name: 'authServer',
id: 'authServer',
status: 'green',
depth: 1,
children: [Object] },
{ parent: 'root',
name: 'dndServer',
id: 'dndServer',
status: [Object],
depth: 1,
children: [Object] },
{ parent: 'root',
name: 'accServer',
id: 'accServer',
status: 'green',
depth: 1,
children: [Object] },
{ parent: 'root',
name: 'contactPolicyServer',
id: 'contactPolicyServer',
status: 'green',
depth: 1,
children: [Object] },
{ parent: 'root',
name: 'DB',
id: 'DB',
status: undefined,
depth: 1 },
{ parent: 'root',
name: 'fileServer',
id: 'fileServer',
status: 'green',
depth: 1,
children: [Object] },
{ parent: 'root',
name: 'campaignServer',
id: 'campaignServer',
status: 'green',
depth: 1,
children: [Object] } ] }
``````

When this gets rendered on browser, I see only one circle drawn, and the web console shows lot of errors, because the svg transformation functions have received a NaN value.

While trying to debug the issue, I found that the the "d" object that is passed to callback function, didn't have keys named 'x' or 'y'. The debug output of object 'd' looks like below:

``````break in ind.js:159
158               .attr('d', function(d) {
>159                 debugger;
160                 return "M" + project(d.x, d.y)
161                       + "C" + project(d.x, (d.y + d.parent.y)/2)
repl
Press Ctrl + C to leave debug repl
> d
{ data:
{ parent: 'root',
name: 'authServer',
id: 'authServer',
status: 'green',
depth: 1,
children: [ [Object], [Object] ] },
height: 1,
depth: 1,
parent:
{ data:
{ parent: null,
name: 'root',
id: 'root',
status: 'green',
depth: 0,
children: [Object] },
height: 2,
depth: 0,
parent: null,
children:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ] },
children:
[ { data: [Object], height: 0, depth: 2, parent: [Object] },
{ data: [Object], height: 0, depth: 2, parent: [Object] } ] }
``````

I am wondering when, where and how the values of d.x and d.y get populated , so that they can be used safely in callback functions...

The `d3.tree()` function sets the `x` and `y` properties. According to the documentation, `d3.tree()`:

Lays out the specified root hierarchy, assigning the following properties on root and its descendants:

• node.x - the x-coordinate of the node
• node.y - the y-coordinate of the node

Thus, since you defined your `d3.tree()`:

``````var tree = d3.tree()
.size([360, 500])
.separation(function(a,b){
return (a.parent == b.parent ? 1 : 2)/a.depth;
});
``````

``````var root = d3.hierarchy(result);
``````

The next step should be:

``````root = tree(root);
``````

That will populate the `x` and `y` properties.