function circleLegend({
scale,
fill = "none",
stroke = "black",
marginTop = 5,
marginRight = 50,
marginBottom = 10,
marginLeft = 1,
ticks = 3,
tickSize = 5,
tickFormat = d => d,
tickValues,
tickStroke = "currentColor",
tickStrokeDash = "4, 2",
tickFont = "12px sans-serif",
tickWrap = false,
tickWrapSpacing = 12,
} = {}) {
ticks = tickValues || scale.ticks(ticks);
const r = scale(d3.max(ticks))
const width = r * 2 + marginRight
const height = r * 2 + marginBottom
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [-marginLeft, -marginTop, width, height])
.attr("overflow", "visible")
svg.selectAll("circle")
.data(ticks)
.join("circle")
.sort((a, b) => b - a)
.attr("fill", fill)
.attr("stroke", stroke)
.attr("cx", r)
.attr("cy", scale)
.attr("r", scale)
svg.selectAll("line")
.data(ticks)
.join("line")
.attr("stroke", tickStroke)
.attr("stroke-dasharray", tickStrokeDash)
.attr("x1", r)
.attr("x2", tickSize + r * 2)
.attr("y1", d => scale(d) * 2)
.attr("y2", d => scale(d) * 2);
const ticksFormatted = ticks
.map((d, i, g) => ({d, text: tickFormat(d, i, g)}))
.map(d => ({ ...d, lines: getLines(d.text, marginRight - (tickSize + 3), tickFont)}))
const tickLabels = svg.selectAll("text")
.data(ticksFormatted)
.join("text")
.attr("transform", ({d}) => `translate(${r * 2 + tickSize + 3}, ${scale(d) * 2})`)
.style("font", tickFont)
if (tickWrap) {
tickLabels
.selectAll("tspan")
.data(d => d.lines)
.join("tspan")
.attr("x", 0)
.attr("y", (d, i, g) => (i - g.length / 2 + 0.8) * tickWrapSpacing)
.text(d => d.text);
} else {
tickLabels
.attr("dominant-baseline", "middle")
.text(d => d.text)
}
return svg.node()
}