Another type of similar diagram is a dendrogram, which uses D3's cluster layout and puts all leaf nodes of a tree at the same depth. Let's create that now. Comment out the westerosChart.init() line in main.js and add this beneath it:
westerosChart.init('cluster', 'data/GoT-lineages-screentimes.json');
Go back to chapter6/index and add the following:
westerosChart.cluster = function Cluster(_data) {
const data = getMajorHouses(_data);
const stratify = d3.stratify()
.parentId(d => d.fatherLabel)
.id(d => d.itemLabel);
const root = stratify(data);
fixateColors(houseNames(root), 'id');
const layout = d3.cluster()
.size([
this.innerWidth - 150,
this.innerHeight,
]);
const links = layout(root)
.descendants()
.slice(1);
}
This should look familiar already--we get our data, create a stratify generator, then use it on our data. We then create a cluster layout, give it a size (though, here we subtract 150 pixels for the legend), then generate the links using layout.descendants().
Still in westerosChart.cluster, add the following:
const line = d3.line().curve(d3.curveBasis);
this.container.selectAll('.link')
.data(links)
.enter()
.append('path')
.attr('fill', 'none')
.attr('stroke', 'lightblue')
.attr('d', d => line([
[d.y, d.x],
[(d.y + d.parent.y) / 2, d.x],
[(d.y + d.parent.y) / 2, d.parent.x],
[d.parent.y, d.parent.x]],
));
This is the same path, drawing bit of code from before, except we've swapped the x and y values so that it displays horizontally instead of vertically.
Next, add circles for the nodes:
const nodes = this.container.selectAll('.node')
.data(root.descendants())
.enter()
.append('circle')
.classed('node', true)
.attr('r', 5)
.attr('fill', getHouseColor)
.attr('cx', d => d.y)
.attr('cy', d => d.x);
Then, add a legend:
const l = legend
.legendColor()
.scale(color);
this.container
.append('g')
.attr('id', 'legend')
.attr('transform', `translate(${this.innerWidth - 100}, 0)`)
.call(l);
Lastly, call the tooltip factory, and we're done!:
nodes.call(tooltip(d => d.data.itemLabel, this.container));
Click on save, and you'll get something like this: