sunburst = {
const root = partition2(flare);
const svg = d3.create("svg");
const label = svg
.append("text")
.attr("text-anchor", "middle")
.attr("fill", "#888")
.style("visibility", "hidden");
label
.append("tspan")
.attr("class", "percentage")
.attr("x", 0)
.attr("y", 0)
.attr("dy", "-0.1em")
.attr("font-size", "3em")
.text("");
label
.append("tspan")
.attr("x", 0)
.attr("y", 0)
.attr("dy", "1.5em")
.text("of visits begin with this sequence");
svg
.attr("viewBox", `${-radius} ${-(radius + breadcrumbHeight * 2)} ${width} ${width + breadcrumbHeight * 2}`)
.style("max-width", `${width}px`)
.style("font", "12px sans-serif");
const gSunburst = svg.append('g');
const gBreadcrumbs = svg.append('g')
.attr('transform', `translate(${-radius}, ${-(radius + breadcrumbHeight * 1.5)})`);
const path = gSunburst
.append("g")
.selectAll("path")
.data(
root.descendants().filter(d => {
// Don't draw the root node, and for efficiency, filter out nodes that would be too small to see
return d.depth && d.x1 - d.x0 > 0.001;
})
)
.join("path")
.attr("fill", d => color(d.data.name))
.attr("d", arc);
gSunburst
.append("g")
.attr("fill", "none")
.attr("pointer-events", "all")
.on("mouseleave", () => {
path.attr("fill-opacity", 1);
label.style("visibility", "hidden");
drawBreadcrumbs([]);
})
.selectAll("path")
.data(
root.descendants().filter(d => {
// Don't draw the root node, and for efficiency, filter out nodes that would be too small to see
return d.depth && d.x1 - d.x0 > 0.001;
})
)
.join("path")
.attr("d", mousearc)
.on("mouseenter", (event, d) => {
// Get the ancestors of the current segment, minus the root
const sequence = d
.ancestors()
.reverse()
.slice(1);
// Highlight the ancestors
path.attr("fill-opacity", node =>
sequence.indexOf(node) >= 0 ? 1.0 : 0.3
);
const percentage = ((100 * d.value) / root.value).toPrecision(3);
label
.style("visibility", null)
.select(".percentage")
.text(percentage + "%");
drawBreadcrumbs(sequence);
});
function drawBreadcrumbs(path) {
path.reverse();
gBreadcrumbs.selectAll('polygon')
.data(path)
.join('polygon')
.attr('transform',
(d, i) => `translate(${(path.length - i - 1) * breadcrumbWidth}, 0)`)
.attr('points', (d, i, p) => breadcrumbPoints(d, i))
.attr('fill', d => color(d.data.name))
.attr('stroke', 'white');
d3.selectAll(".breadcrumb-labels").remove();
const breadcrumbLabels = gBreadcrumbs
.selectAll("text")
.data(path)
.join("text")
.attr(
"transform",
(d, i) => `translate(${(path.length - i - 1) * breadcrumbWidth}, 0)`
)
.attr("text-anchor", "middle")
.attr("pointer-events", "none")
.style("user-select", "none")
.attr("fill", "white");
breadcrumbLabels
.append("tspan")
.attr("class", "breadcrumb-labels")
.attr("x", breadcrumbWidth / 2)
.attr("y", breadcrumbHeight / 2)
.attr("dy", 2)
.text(d => d.data.name);
}
return svg.node();
}