ringObjHTML = (ring) => {
const {
cx,
cy,
r,
innerR,
padAngle = 1,
color = "red",
data,
strokeWidth = 2,
bold = true
} = ring;
const halfPI = Math.PI / 2;
const svg = d3.create("svg");
const arc = d3
.arc()
.innerRadius(r)
.outerRadius(r + innerR)
.padAngle((Math.PI / 180) * padAngle)
.startAngle((d) => (Math.PI / 180) * d.startAngle)
.endAngle((d) => (Math.PI / 180) * d.endAngle);
const atBottom = (d) => {
const middle =
((Math.PI / 180) * d.startAngle -
halfPI +
(Math.PI / 180) * 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,
(Math.PI / 180) * d.endAngle - halfPI,
(Math.PI / 180) * d.startAngle - halfPI,
true
);
} else {
context.arc(
0,
0,
r,
(Math.PI / 180) * d.startAngle - halfPI,
(Math.PI / 180) * 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) ? +1.15 : -0.85))
.attr("dominant-baseline", "middle")
.attr("text-anchor", "middle")
.append("textPath")
.attr("startOffset", "50%")
.attr("xlink:href", (d) => d.uid.href)
.text((d) =>
d.letterSpace
? d.text.split("").join("\xa0".repeat(d.letterSpace))
: d.text
);
};
data.forEach((d) => (d.uid = DOM.uid("p-" + d.index)));
svg.selectAll("g.arcLabel").data(data).join(enter);
return svg.node().innerHTML;
}