Creating a legend for a d3.scaleSequential

I’d like to create a legend for a d3.scaleSequential – something like this colour ramp with an axis component. What I’m weighing up is whether to use all-SVG, all-Canvas, or SVG for the axis component and SVG for the colour ramp.

I’ve had a look at d3-legend, but it doesn’t quite communicate the continuous nature of d3.scaleSequential. I’ve also considered using an SVG linearGradient, but this would mean using two interpolators – one for d3.scaleSequential and one for linearGradient.

I’d be interested to know how others would create a legend. Thanks in advance for your suggestions!

Hi Iaian!

Sure, here’s an example of a continuous d3.scaleSequential legend: https://beta.observablehq.com/@tmcw/d3-scalesequential-continuous-color-legend-example

You can get away using just one scale by doing a little magic in the .map() call in linearGradient, as demonstrated in that notebook.

Between SVG and Canvas, there’s not too much much of an implementation difference, but I’d wager that the SVG path is a bit simpler, because you don’t have to use foreignObject or anything like that. Nadieh Bremer has an excellent article about this problem that’d be useful as a reference.

Hope that helps!

My preference for this task is to use canvas.toDataURL: generate the canvas as in my color ramp notebook, then embed the canvas in SVG as an image element with a data URL.

https://beta.observablehq.com/@mbostock/continuous-color-guide

That said, you can’t use the image-rendering: pixelated style with this technique, which means it’s not suitable for discrete color scales. But for discrete color scales, you could use simple rect elements for each color. Also, some further thought is required for how to construct color guides for non-linear scales and piecewise scales with more than two elements in the domain.

Thank you @tom and @mbostock for your comments. I’ll investigate and report back :smiley: