function Sunburst(data, {
path,
id = Array.isArray(data) ? d => d.id : null,
parentId = Array.isArray(data) ? d => d.parentId : null,
children,
value,
sort = (a, b) => d3.descending(a.value, b.value),
label,
title,
link,
linkTarget = "_blank",
width = 640,
height = 400,
margin = 1,
marginTop = margin,
marginRight = margin,
marginBottom = margin,
marginLeft = margin,
padding = 1,
startAngle = 0,
endAngle = 2 * Math.PI,
radius = Math.min(width - marginLeft - marginRight, height - marginTop - marginBottom) / 2,
color = d3.interpolateRainbow,
fill = "#ccc",
fillOpacity = 0.6,
} = {}) {
const root = path != null ? d3.stratify().path(path)(data)
: id != null || parentId != null ? d3.stratify().id(id).parentId(parentId)(data)
: d3.hierarchy(data, children);
value == null ? root.count() : root.sum(d => Math.max(0, value(d)));
if (sort != null) root.sort(sort);
d3.partition().size([endAngle - startAngle, radius])(root);
if (color != null) {
color = d3.scaleSequential([0, root.children.length], color).unknown(fill);
root.children.forEach((child, i) => child.index = i);
}
const arc = d3.arc()
.startAngle(d => d.x0 + startAngle)
.endAngle(d => d.x1 + startAngle)
.padAngle(d => Math.min((d.x1 - d.x0) / 2, 2 * padding / radius))
.padRadius(radius / 2)
.innerRadius(d => d.y0)
.outerRadius(d => d.y1 - padding);
const svg = d3.create("svg")
.attr("viewBox", [
marginRight - marginLeft - width / 2,
marginBottom - marginTop - height / 2,
width,
height
])
.attr("width", width)
.attr("height", height)
.attr("style", "max-width: 100%; height: auto; height: intrinsic;")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "middle");
const cell = svg
.selectAll("a")
.data(root.descendants())
.join("a")
.attr("xlink:href", link == null ? null : d => link(d.data, d))
.attr("target", link == null ? null : linkTarget);
cell.append("path")
.attr("d", arc)
.attr("fill", color ? d => color(d.ancestors().reverse()[1]?.index) : fill)
.attr("fill-opacity", fillOpacity);
if (label != null) cell
.filter(d => (d.y0 + d.y1) / 2 * (d.x1 - d.x0) > 10)
.append("text")
.attr("transform", d => {
if (!d.depth) return;
const x = ((d.x0 + d.x1) / 2 + startAngle) * 180 / Math.PI;
const y = (d.y0 + d.y1) / 2;
return `rotate(${x - 90}) translate(${y},0) rotate(${x < 180 ? 0 : 180})`;
})
.attr("dy", "0.32em")
.text(d => label(d.data, d));
if (title != null) cell.append("title")
.text(d => title(d.data, d));
return svg.node();
}