Skip to content

Instantly share code, notes, and snippets.

@d3noob d3noob/.block

Last active Jul 2, 2020
Embed
What would you like to do?
Interactive d3.js tree diagram
license: mit

This is a d3.js tree diagram that incldes an interactive element as used as an example in the book D3 Tips and Tricks.

Any parent node can be clicked on to collapse the portion of the tree below it, on itself. Conversly, it can be clicked on again to regrow.

It is derived from the Mike Bostock Collapsible tree example but it is a slightly cut down version.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tree Example</title>
<style>
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
</style>
</head>
<body>
<!-- load the d3.js library -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<script>
var treeData = [
{
"name": "Top Level",
"parent": "null",
"children": [
{
"name": "Level 2: A",
"parent": "Top Level",
"children": [
{
"name": "Son of A",
"parent": "Level 2: A"
},
{
"name": "Daughter of A",
"parent": "Level 2: A"
}
]
},
{
"name": "Level 2: B",
"parent": "Top Level"
}
]
}
];
// ************** Generate the tree diagram *****************
var margin = {top: 20, right: 120, bottom: 20, left: 120},
width = 960 - margin.right - margin.left,
height = 500 - margin.top - margin.bottom;
var i = 0,
duration = 750,
root;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
root = treeData[0];
root.x0 = height / 2;
root.y0 = 0;
update(root);
d3.select(self.frameElement).style("height", "500px");
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 180; });
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); });
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
.on("click", click);
nodeEnter.append("circle")
.attr("r", 1e-6)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeEnter.append("text")
.attr("x", function(d) { return d.children || d._children ? -13 : 13; })
.attr("dy", ".35em")
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
.text(function(d) { return d.name; })
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
nodeUpdate.select("circle")
.attr("r", 10)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {x: source.x0, y: source.y0};
return diagonal({source: o, target: o});
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {x: source.x, y: source.y};
return diagonal({source: o, target: o});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
// Toggle children on click.
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
</script>
</body>
</html>
@erapisardi

This comment has been minimized.

Copy link

erapisardi commented Nov 16, 2019

Hi, I am using your tree diagram, but as I have long text for level 3 of the tree I would wrap the text. But as I am just a beginner I don't know how to do it. Thanks!

@d3noob

This comment has been minimized.

Copy link
Owner Author

d3noob commented Nov 16, 2019

I haven't done this myself, but a bit of a google indicates that there are some ways of accomplishing it. Try this for a start https://stackoverflow.com/questions/24784302/wrapping-text-in-d3

@erapisardi

This comment has been minimized.

Copy link

erapisardi commented Nov 17, 2019

Thank you for your reply! I tried the solution you suggested, but it did not work, probably because I did not insert the code in the right line.

@d3noob

This comment has been minimized.

Copy link
Owner Author

d3noob commented Nov 17, 2019

Okay, my second suggestion is to check out some of the examples in block builder for text wrapping and see if you can find one that matches the version of d3 you are using and the type of visualisation you are trying to implement. You can start here - https://blockbuilder.org/search?text=text+wrap&thumb=true
If that doesn't work, try raising a question in the d3 section on stack overflow here - https://stackoverflow.com/questions/tagged/d3.js
Best of luck.

@wujoho

This comment has been minimized.

Copy link

wujoho commented Jan 23, 2020

Hi, is it possible to make this project compatible with latest D3 version? I tried https://d3js.org/d3.v5.min.js and it didn't work.
Thanks

@d3noob

This comment has been minimized.

Copy link
Owner Author

d3noob commented Jan 24, 2020

Hi, is it possible to make this project compatible with latest D3 version? I tried https://d3js.org/d3.v5.min.js and it didn't work.
Thanks

Funny you should ask. I recently updated all the examples from the book into v5. Check this example out.

@prashmalyala

This comment has been minimized.

Copy link

prashmalyala commented Jun 30, 2020

Hi, thanks for this great diagram! I was reading through the code + playing around with it on JSFiddle but am having trouble understanding how all the positioning is done. Is there a convenient way to rotate this visualization so I can represent a more hierarchical structure?

@d3noob

This comment has been minimized.

Copy link
Owner Author

d3noob commented Jul 1, 2020

Hi, thanks for this great diagram! I was reading through the code + playing around with it on JSFiddle but am having trouble understanding how all the positioning is done. Is there a convenient way to rotate this visualization so I can represent a more hierarchical structure?

Sure! This example uses a pretty old version of d3. I reccomend changing to version 5 and you can find examples for a vertical layout from other examples here or you can get a full explanation of how the code works in the free book here

@prashmalyala

This comment has been minimized.

Copy link

prashmalyala commented Jul 2, 2020

Hi, thanks for this great diagram! I was reading through the code + playing around with it on JSFiddle but am having trouble understanding how all the positioning is done. Is there a convenient way to rotate this visualization so I can represent a more hierarchical structure?

Sure! This example uses a pretty old version of d3. I reccomend changing to version 5 and you can find examples for a vertical layout from other examples here or you can get a full explanation of how the code works in the free book here

The eBook helped lots; got it working. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.