Skip to content

Instantly share code, notes, and snippets.

@maury91
Forked from d3noob/.block
Last active October 5, 2016 07:48
Show Gist options
  • Save maury91/2cf3ca8887c344ecb49b5b422f31e3ef to your computer and use it in GitHub Desktop.
Save maury91/2cf3ca8887c344ecb49b5b422f31e3ef to your computer and use it in GitHub Desktop.
Simple vertical d3.js tree diagram

This is a simple d3.js tree diagram, arranged so that the tree is vertical, as used as an example in the book D3 Tips and Tricks.

It is derived from the Mike Bostock Collapsible tree example but it is a VERY cut down version without the ability to update (collapse).

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 10px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 120, bottom: 20, left: 120},
width = 10000 - margin.right - margin.left,
height = window.innerHeight - 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 + ")");
function convertRootBranch(branch) {
return {
name: branch.lemma + '( ' + branch.tag + ' )' + '[ ' + branch.text + ' ]',
children: branch.children.map(convertBranch)
}
}
function convertBranch(branch) {
var result = {
name: branch.label,
children: [{
name: branch.child.lemma + '( ' + branch.child.tag + ' )' + '[ ' + branch.child.text + ' ]'
}]
}
if (branch.child.children.length) {
result.children[0].children = branch.child.children.map(convertBranch)
}
return result
}
d3.json("https://gist.githubusercontent.com/maury91/2cf3ca8887c344ecb49b5b422f31e3ef/raw/47eb0ac1ec3765360d6d7f7bbfdd4af5bbcd6022/tree.json", function(error, tree) {
if (error) throw error;
root = {
name: 'root',
children: tree.map(convertRootBranch)
}
root.x0 = height / 2;
root.y0 = 0;
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
console.log(root.children)
root.children.forEach(collapse);
update(root);
});
d3.select(self.frameElement).style("height", "800px");
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 ? -10 : 10; })
.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", 4.5)
.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>
[{"text":"was","beginOffset":-1,"tag":"VERB","lemma":"be","index":4,"children":[{"label":"NSUBJ","child":{"text":"experience","beginOffset":-1,"tag":"NOUN","lemma":"experience","index":3,"children":[{"label":"DET","child":{"text":"the","beginOffset":-1,"tag":"DET","lemma":"the","index":0,"children":[]}},{"label":"NN","child":{"text":"service","beginOffset":-1,"tag":"NOUN","lemma":"service","index":2,"children":[{"label":"NN","child":{"text":"customer","beginOffset":-1,"tag":"NOUN","lemma":"customer","index":1,"children":[]}}]}}]}},{"label":"ACOMP","child":{"text":"awful","beginOffset":-1,"tag":"ADJ","lemma":"awful","index":5,"children":[]}}]}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment