function drawLegend({
color,
title,
tickSize = 6,
width = 320,
height = 44 + tickSize,
marginTop = 18,
marginRight = 20,
marginBottom = 16 + tickSize,
marginLeft = 0,
ticks = width / 64,
tickFormat,
tickValues
} = {}) {
const svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.style("overflow", "hidden")
.style("display", "block");
const x = Object.assign(
color
.copy()
.interpolator(d3.interpolateRound(marginLeft, width - marginRight)),
{
range() {
return [marginLeft, width - marginRight];
}
}
);
svg
.append("image")
.attr("x", marginLeft)
.attr("y", marginTop)
.attr("width", width - marginLeft - marginRight)
.attr("height", height - marginTop - marginBottom)
.attr("preserveAspectRatio", "none")
.attr("xlink:href", ramp(color.interpolator()).toDataURL());
const axis = d3
.axisBottom(x)
.ticks(ticks, typeof tickFormat === "string" ? tickFormat : undefined)
.tickFormat(typeof tickFormat === "function" ? tickFormat : undefined)
.tickSize(tickSize)
.tickValues(tickValues);
const g = svg
.append("g")
.attr("transform", `translate(0, ${height - marginBottom})`)
.style("font-family", "sans-serif")
.call(axis)
.call(g =>
g.selectAll(".tick line").attr("y1", marginTop + marginBottom - height)
)
.call(g =>
g
.select(".domain")
.attr("stroke-width", 0)
.remove()
)
.call(g =>
g
.append("text")
.attr("y", marginTop + marginBottom - height - 6)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text(title)
);
return Object.assign(svg.node(), {
update(domain) {
x.domain(domain);
g.transition()
.duration(500)
.call(axis)
.call(g =>
g
.selectAll(".tick line")
.attr("y1", marginTop + marginBottom - height)
)
.call(g =>
g
.select(".domain")
.attr("stroke-width", 0)
.remove()
);
}
});
}