chart = {
const root = d3.hierarchy(data, d => d.branchset)
.sum(d => d.branchset ? 0 : 1)
.sort((a, b) => (a.value - b.value) || d3.ascending(a.data.length, b.data.length));
cluster(root);
setRadius(root, root.data.length = 0, innerRadius / maxLength(root));
setColor(root);
const svg = d3.create("svg")
.attr("viewBox", [-outerRadius, -outerRadius, width, width])
.attr("font-family", "sans-serif")
.attr("font-size", 10);
svg.append("g")
.call(legend);
svg.append("style").text(`
.link--active {
stroke: #000 !important;
stroke-width: 1.5px;
}
.link-extension--active {
stroke-opacity: .6;
}
.label--active {
font-weight: bold;
}
`);
const linkExtension = svg.append("g")
.attr("fill", "none")
.attr("stroke", "#000")
.attr("stroke-opacity", 0.25)
.selectAll("path")
.data(root.links().filter(d => !d.target.children))
.join("path")
.each(function(d) { d.target.linkExtensionNode = this; })
.attr("d", linkExtensionConstant);
const link = svg.append("g")
.attr("fill", "none")
.attr("stroke", "#000")
.selectAll("path")
.data(root.links())
.join("path")
.each(function(d) { d.target.linkNode = this; })
.attr("d", linkConstant)
.attr("stroke", d => d.target.color);
svg.append("g")
.selectAll("text")
.data(root.leaves())
.join("text")
.attr("dy", ".31em")
.attr("transform", d => `rotate(${d.x - 90}) translate(${innerRadius + 4},0)${d.x < 180 ? "" : " rotate(180)"}`)
.attr("text-anchor", d => d.x < 180 ? "start" : "end")
.text(d => d.data.name.replace(/_/g, " "))
.on("mouseover", mouseovered(true))
.on("mouseout", mouseovered(false));
function update(checked) {
const t = d3.transition().duration(750);
linkExtension.transition(t).attr("d", checked ? linkExtensionVariable : linkExtensionConstant);
link.transition(t).attr("d", checked ? linkVariable : linkConstant);
}
function mouseovered(active) {
return function(event, d) {
d3.select(this).classed("label--active", active);
d3.select(d.linkExtensionNode).classed("link-extension--active", active).raise();
do d3.select(d.linkNode).classed("link--active", active).raise();
while (d = d.parent);
};
}
return Object.assign(svg.node(), {update});
}