Public
Edited
Feb 23, 2024
17 forks
41 stars
Insert cell
Insert cell
canvas = {
const svg = d3.create("svg").attr("viewBox", [-10, -10, width, height]);
const root = new Node;
const nodes = [root];
const links = [];

tree(root);

let link = svg.append("g")
.attr("fill", "none")
.attr("stroke", "#000")
.selectAll(".link");

let node = svg.append("g")
.attr("stroke", "#fff")
.attr("stroke-width", 2)
.selectAll(".node");

const interval = d3.interval(() => {
if (nodes.length >= 500) return interval.stop();

// Add a new node to a random parent.
const parent = nodes[Math.random() * nodes.length | 0];
const child = Object.assign(new Node, {parent, depth: parent.depth + 1});
if (parent.children) parent.children.push(child);
else parent.children = [child];
nodes.push(child);
links.push({source: parent, target: child});

// Recompute the layout.
tree(root);

// Add entering nodes in the parent’s old position.
node = node.data(nodes);
node = node.enter().append("circle")
.attr("class", "node")
.attr("r", 4)
.attr("cx", d => d.parent ? d.parent.px : d.px = d.x)
.attr("cy", d => d.parent ? d.parent.py : d.py = d.y)
.merge(node);

// Add entering links in the parent’s old position.
link = link.data(links);
link = link.enter().insert("path", ".node")
.attr("class", "link")
.attr("d", d => {
const o = {x: d.source.px, y: d.source.py};
return renderLink({source: o, target: o});
})
.merge(link);

// Transition nodes and links to their new positions.
const t = svg.transition()
.duration(duration);

link.transition(t)
.attr("d", renderLink);

node.transition(t)
.attr("cx", d => d.px = d.x)
.attr("cy", d => d.py = d.y);
}, duration);

invalidation.then(() => interval.stop());

return svg.node();
}
Insert cell
tree = d3.tree().size([width - 20, height - 20])
Insert cell
Insert cell
Node = d3.hierarchy.prototype.constructor
Insert cell
height = 600
Insert cell
duration = 750
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more