ringHTML = (
cx,
cy,
r,
innerR,
padAngle,
color,
data,
strokeWidth = 2,
bold = true
) => {
const halfPI = Math.PI / 2;
const svg = d3.create("svg");
const arc = d3
.arc()
.innerRadius(r - innerR)
.outerRadius(r)
.padAngle((Math.PI / 180) * padAngle);
const atBottom = (d) => {
const middle = (d.startAngle - halfPI + d.endAngle - halfPI) / 2;
return middle >= 0 && middle < Math.PI;
};
const enter = (enter) => {
const g = enter
.append("g")
.attr("class", "arcLabel")
.attr("transform", `translate(${cx}, ${cy})`);
g.append("path")
.attr("id", (d) => d.uid.id)
.style("fill", "none")
.attr("d", (d) => {
const context = d3.path();
if (atBottom(d)) {
context.arc(
0,
0,
r,
d.endAngle - halfPI,
d.startAngle - halfPI,
true
);
} else {
context.arc(
0,
0,
r,
d.startAngle - halfPI,
d.endAngle - halfPI,
false
);
}
return context.toString();
});
g.append("path")
.style("stroke", strokeWidth != 0 ? (d) => color(d.uid) : null)
.style("stroke-width", strokeWidth)
.style("fill", strokeWidth != 0 ? "transparent" : (d) => color(d.uid))
.attr("d", (d) => arc(d));
g.append("text")
.style("fill", strokeWidth != 0 ? (d) => color(d.uid) : "white")
.style("font-size", (d) => (d.fontSize ? d.fontSize : 12))
.style("font-weight", bold ? "bold" : "normal")
.attr("dy", (d) => (innerR / 2) * (atBottom(d) ? -0.9 : 1.15))
.attr("dominant-baseline", "middle")
.attr("text-anchor", "middle")
.append("textPath")
.attr("startOffset", "50%")
.attr("startOffset", (d) =>
d.textOffAngle ? 50 + d.textOffAngle + "%" : "50%"
)
.attr("xlink:href", (d) => d.uid.href)
.text((d) =>
d.space ? d.data.split("").join("\xa0".repeat(d.space)) : d.data
);
};
data.forEach((d) => (d.uid = DOM.uid("p-" + d.index)));
svg.selectAll("g.arcLabel").data(data).join(enter);
return svg.node().innerHTML;
}