D3.js Hierarchies — Tree and Cluster Layouts
In this tutorial, you will learn about D3.js Hierarchies. We cover key concepts, practical examples, and best practices to help you master this topic.
D3.js hierarchical layouts transform nested data into tree diagrams, cluster charts, treemaps, and partition layouts for visualizing parent-child relationships.
What You'll Learn
By the end of this guide, you will create trees from hierarchical data, use d3.stratify for flat data, build treemaps for proportion visualization, create dendrograms, and add interactive collapse/expand.
Why Hierarchies Matter
Hierarchical data is everywhere. In Durga Antivirus Pro, the threat classification tree shows malware categories and subcategories, helping analysts navigate the taxonomy of known threats.
flowchart TD
A[Root] --> B[Category A]
A --> C[Category B]
B --> D[Sub A1]
B --> E[Sub A2]
C --> F[Sub B1]
C --> G[Sub B2]
Creating a Tree Layout
var data = {
name: 'Root',
children: [
{ name: 'Branch 1', children: [
{ name: 'Leaf 1A' },
{ name: 'Leaf 1B' }
]},
{ name: 'Branch 2', children: [
{ name: 'Leaf 2A' },
{ name: 'Leaf 2B' }
]}
]
};
var root = d3.hierarchy(data);
var treeLayout = d3.tree().size([400, 300]);
treeLayout(root);
Rendering the Tree
// Links
svg.append('g')
.selectAll('path')
.data(root.links())
.enter()
.append('path')
.attr('fill', 'none')
.attr('stroke', '#555')
.attr('stroke-width', 2)
.attr('d', d3.linkHorizontal()
.x(function(d) { return d.y; })
.y(function(d) { return d.x; })
);
// Nodes
svg.append('g')
.selectAll('circle')
.data(root.descendants())
.enter()
.append('circle')
.attr('cx', function(d) { return d.y; })
.attr('cy', function(d) { return d.x; })
.attr('r', 5);
Using d3.stratify for Flat Data
var data = [
{ id: 'A', parent: '' },
{ id: 'B', parent: 'A' },
{ id: 'C', parent: 'A' },
{ id: 'D', parent: 'B' },
{ id: 'E', parent: 'B' }
];
var root = d3.stratify()
.id(function(d) { return d.id; })
.parentId(function(d) { return d.parent; })
(data);
var tree = d3.tree().size([400, 300]);
tree(root);
Treemap
var root = d3.hierarchy(data)
.sum(function(d) { return d.value || 0; });
d3.treemap()
.size([500, 400])
.padding(2)
(root);
svg.selectAll('rect')
.data(root.leaves())
.enter()
.append('rect')
.attr('x', function(d) { return d.x0; })
.attr('y', function(d) { return d.y0; })
.attr('width', function(d) { return d.x1 - d.x0; })
.attr('height', function(d) { return d.y1 - d.y0; })
.attr('fill', function(d) { return d.data.color || '#4ecdc4'; });
Common Mistakes
1. Calling Layout Before hierarchy
The layout functions require a d3.hierarchy root. Always wrap data with d3.hierarchy() first.
2. Not Summing for Treemap
Treemap needs .sum() to compute leaf values. Without it, all leaves have the same size.
3. Forgetting That Tree Layout Inverts X and Y
By default, d3.tree uses x for vertical position and y for horizontal. Use .size([height, width]) if you want horizontal layout.
4. Data With Cycles
d3.hierarchy requires acyclic data. Circular references in children cause infinite Recursion.
5. Not Handling Missing Parent References in Stratify
Nodes with parent="" must have a root node where parent is null or the parent exists. Orphaned nodes throw errors.
Practice Questions
Q1: What is the difference between d3.tree and d3.cluster? A: d3.tree spreads leaf nodes to avoid overlap. d3.cluster places all leaves at the same depth.
Q2: What does d3.hierarchy() do? A: It converts a nested JSON object into a d3 hierarchy node with properties like children, depth, height, and parent.
Q3: How do you convert flat tabular data to hierarchy? A: Use d3.stratify() with an id accessor and parentId accessor.
Q4: What is the purpose of .sum() in treemap? A: It computes the total value for each node, which determines the size of treemap rectangles.
Q5: How do you create a collapsible tree?
A: Add click handlers on nodes that toggle the visibility of child nodes. Use node.children and node._children.
Challenge: Build an interactive organizational chart. Load employee data as flat CSV with manager IDs. Render a tree. Click employees to expand/collapse their teams. Highlight the chain of command on hover.
FAQ
Try It Yourself
Build an interactive tree diagram with expandable branches.
<!DOCTYPE html>
<html>
<head>
<title>Interactive Tree</title>
<style>
body { font-family: sans-serif; padding: 20px; background: #f5f5f5; }
.node circle { fill: #4ecdc4; stroke: #2a9d8f; stroke-width: 2; cursor: pointer; }
.node text { font-size: 12px; fill: #333; }
.link { fill: none; stroke: #ccc; stroke-width: 2; }
</style>
</head>
<body>
<svg width="600" height="450" id="tree"></svg>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
var data = {
name: 'CEO', children: [
{ name: 'CTO', children: [
{ name: 'Dev Lead', children: [{ name: 'Engineer A' }, { name: 'Engineer B' }] },
{ name: 'QA Lead', children: [{ name: 'Tester A' }, { name: 'Tester B' }] }
]},
{ name: 'CFO', children: [
{ name: 'Accountant A' }, { name: 'Accountant B' }
]},
{ name: 'CMO' }
]
};
var width = 600, height = 450;
var svg = d3.select('#tree').append('g').attr('transform', 'translate(60, 40)');
var root = d3.hierarchy(data);
var tree = d3.tree().size([height - 80, width - 120]);
tree(root);
svg.selectAll('.link')
.data(root.links()).enter()
.append('path').attr('class', 'link')
.attr('d', d3.linkHorizontal().x(function(d) { return d.y; }).y(function(d) { return d.x; }));
var node = svg.selectAll('.node')
.data(root.descendants()).enter()
.append('g').attr('class', 'node')
.attr('transform', function(d) { return 'translate(' + d.y + ',' + d.x + ')'; });
node.append('circle').attr('r', 5);
node.append('text').attr('x', 8).attr('y', 4).text(function(d) { return d.data.name; });
</script>
</body>
</html>
What's Next
Create geographic map visualizations.
Geo Maps — Geographic mapping with D3.js. Request Data — Loading external data in D3.js.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro