Skip to content

Instantly share code, notes, and snippets.

@willzjc
Last active January 6, 2018 22:15
Show Gist options
  • Save willzjc/08e4e45d6d13fbcc9063cbb305b9f864 to your computer and use it in GitHub Desktop.
Save willzjc/08e4e45d6d13fbcc9063cbb305b9f864 to your computer and use it in GitHub Desktop.
Random Tree
license: mit

This example builds a random tree using the Reingold-Tilford "tidy" algorithm, as described in "Tidier Drawings of Trees" and implemented by d3.layout.tree. As each node is added to the graph, it enters from the previous position of the parent node. Thus, the existing nodes and the new node transition smoothly to their new positions. The animation stops when 500 nodes have been added to the tree.

forked from wcjohnson11's block: Random Tree

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.node {
stroke: #fff;
stroke-width: 2px;
}
.link {
fill: none;
stroke: #000;
}
</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>
var width = 960,
height = 500;
var tree = d3.layout.tree()
.size([width - 20, height - 20]);
var root = {},
nodes = tree(root);
root.parent = root;
root.px = root.x;
root.py = root.y;
var diagonal = d3.svg.diagonal();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(10,10)");
var node = svg.selectAll(".node"),
link = svg.selectAll(".link");
var duration = 750,
timer = setInterval(update, duration);
function update() {
if (nodes.length >= 500) return clearInterval(timer);
// Add a new node to a random parent.
var n = {id: nodes.length},
p = nodes[Math.random() * nodes.length | 0];
if (p.children) p.children.push(n); else p.children = [n];
nodes.push(n);
// Recompute the layout and data join.
node = node.data(tree.nodes(root), function(d) { return d.id; });
link = link.data(tree.links(nodes), function(d) { return d.source.id + "-" + d.target.id; });
// Add entering nodes in the parent’s old position.
node.enter().append("circle")
.attr("class", "node")
.attr("r", 4)
.attr("cx", function(d) { return d.parent.px; })
.attr("cy", function(d) { return d.parent.py; });
// Add entering links in the parent’s old position.
link.enter().insert("path", ".node")
.attr("class", "link")
.attr("d", function(d) {
var o = {x: d.source.px, y: d.source.py};
return diagonal({source: o, target: o});
});
// Transition nodes and links to their new positions.
var t = svg.transition()
.duration(duration);
t.selectAll(".link")
.attr("d", diagonal);
t.selectAll(".node")
.attr("cx", function(d) { return d.px = d.x; })
.attr("cy", function(d) { return d.py = d.y; });
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment