Getting swatches from a 'scales' color theme

One of the biggest difficulties I have with Observable (due to Javascript) is understanding how to pass values through nested functions… Here is an example:

I would like users to pick a color them and see the swatches that will be used for the amount of data they have.

Observable with this set up: Scales to Swatch Generator / kalmdown / Observable

The cell to pick a color from:

viewof intScale = Inputs.select(Object.keys(scales), {value: 'viridis', label: 'Internal locations color scheme'})

The interpolator using the scale:

intColor = d3.scaleOrdinal()
    .domain(internalLocations.map(d => d.id))
    .range(d3.quantize(t => {
      const {l, c, h} = d3.lch(scales[intScale](t))
      return d3.lch(80, 30, h)
    }, internalLocations.length + 1))

Trying to use the scale directly. Expect 4 swatches.

swatches(scales[intScale],internalLocations)

Trying to use the scale through the interpolator. Expect same 4 swatches.

swatches(scales[intScale](internalLocations.map((d,i) => i)))

My imports:

import { scales } from '@makio135/give-me-colors'
import { select } from '@jashkenas/inputs'
import { ramp, swatches } from '@mbostock/working-with-color'

For a cells description it would be helpful if Observable could provide better info on the function it thinks it is returning, instead of just “ƒ(i)”
image
In this case, is it returning d3.interpolateViridis…no way to know.

1 Like

So, if scales['viridis'] is d3.interpolateViridis, you need to pass it a number in [0, 1] to compute a color. Currently you are passing it internalLocations.map((d, i) => i which means you are calling it once, passing in [0, 1, 2, 3], returning a single color.

Something like this?

swatches(d3.quantize(scales[intScale], internalLocations.length))

Which is like saying

swatches([0/3, 1/3, 2/3, 3/3].map(t => scales[intScale](t)))

Or equivalently

swatches([scales[intScale](0/3), scales[intScale](1/3), scales[intScale](2/3), scales[intScale](3/3)])

Unfortunately JavaScript doesn’t provide much additional information to show here. You can view the source of a function by saying:

d3.interpolateViridis + ""

But in this case you’ll get something equally inscrutable:

"function (e){return t[Math.max(0,Math.min(n-1,Math.floor(e*n)))]}"
1 Like

Thank you! And thank you for unpacking it.

As to the function part. If Observable was built into an IDE (vs in browser) would the IDE be able to maintain state enough to make the function accessible?

Hmmm…running it through the interpolator returns the swatches in reverse order…
swatches(d3.quantize(intColor, internalLocations.length))

Can see in Observable…