Public
Edited
Aug 6, 2023
Importers
2 stars
Insert cell
Insert cell
Insert cell
scalesHex
Insert cell
Insert cell
space = colorSpaces.munsell
Insert cell
Insert cell
[85, 30].map(hexFromLuminance)
Insert cell
Insert cell
["#e7e7e7", "#293133"].map(luminanceFromHex)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
surfaces = [
{
hue: "blues",
surface: ColorSurface.fromHue(-97, { dHue100: -0.58, space: space })
},
{
hue: "oranges",
surface: ColorSurface.fromHue(57, {
dHue100: 0.58,
lum100: 57,
space: space
})
}
]
Insert cell
Insert cell
controlPointsFloating = [
{ luminance: 30, chroma: 7.5 },
{ luminance: 50, chroma: 15 },
{ luminance: 65, chroma: 15 },
{ luminance: 85, chroma: 7.5 }
]
Insert cell
trajectories = [
{
type: "float",
mode: "dark",
controlPoints: controlPointsFloating
},
{
type: "float",
mode: "light",
controlPoints: controlPointsFloating.toReversed()
},
{
type: "fixed",
mode: "dark",
controlPoints: [
{ luminance: 30, chroma: 0 },
{ luminance: 32.5, chroma: 7.5 },
{ luminance: 50, chroma: 15 },
{ luminance: 65, chroma: 15 },
{ luminance: 85, chroma: 7.5 }
]
},
{
type: "fixed",
mode: "light",
controlPoints: [
{ luminance: 85, chroma: 0 },
{ luminance: 82.5, chroma: 7.5 },
{ luminance: 65, chroma: 15 },
{ luminance: 50, chroma: 15 },
{ luminance: 30, chroma: 7.5 }
]
}
].map((x) => ({
type: x.type,
mode: x.mode,
trajectory: new ColorTrajectory(x.controlPoints)
}))
Insert cell
scales = tidy.tidy(
surfaces,
tidy.fullJoin(trajectories),
tidy.mutate({
scale: (d) => new ColorScaleSequential(d.surface, d.trajectory),
data100: (d) => d3.ticks(0, 1, 10).map(d.scale.data100)
})
)
Insert cell
// horrible unnesting, TODO - file with tidyjs?
scalesUnnest = scales
.map((v) =>
v.data100.map((x) => ({ hue: v.hue, type: v.type, mode: v.mode, ...x }))
)
.reduce((a, v) => [...a, ...v])
Insert cell
Insert cell
Insert cell
scalesSequentialFlat = scales.map((x) => ({
name: `${x.hue}-${x.type}-${x.mode}`,
scale: x.scale
}))
Insert cell
getScale = (name, array) =>
array.filter((x) => name === x.name).map((x) => x.scale)[0]
Insert cell
getScale("blues-fixed-light", scalesSequentialFlat)
Insert cell
scalesDivergingFlat = [
{
name: "bluesOranges-fixed-light",
components: ["blues-fixed-light", "oranges-fixed-light"],
scale: 0.8
},
{
name: "bluesOranges-fixed-dark",
components: ["blues-fixed-dark", "oranges-fixed-dark"],
scale: 0.8
}
].map((d) => ({
name: d.name,
scale: new ColorScaleDiverging(
...d.components.map((x) => getScale(x, scalesSequentialFlat)),
{
scale: d.scale
}
)
}))
Insert cell
scalesFlat = [...scalesSequentialFlat, ...scalesDivergingFlat]
Insert cell
namesWithoutMode = _.uniq(
scalesFlat.map((x) => x.name.split("-").slice(0, 2).join("-"))
)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
scaleLocal = getScale(scale, scalesFlat)
Insert cell
## Export

Let's make our scales available elsewhere; we can create array of objects, each with the `name` of the scale, and `values` are an array of hex-codes we can use to re-create the scale.
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
hexFromLuminance = _.flow([
(x) => [x, 0, 0],
space.from100,
space.toSRgb,
colorUtils.hexFromSRgb
])
Insert cell
luminanceFromHex = _.flow([
colorUtils.hexToSRgb,
colorSpaces.munsell.fromSRgb,
colorSpaces.munsell.to100,
(x) => x[0]
])
Insert cell
Insert cell
tidy = import("https://unpkg.com/@tidyjs/tidy@2.5.2/dist/es/index.js?module")
Insert cell
import {
colorSpaces,
colorUtils,
ColorSpace,
ColorSurface,
ColorTrajectory,
ColorScaleSequential,
ColorScaleDiverging
} from "@ijlyttle/color-utilities"
Insert cell
import { inputCvd, matrixCvd } from "@ijlyttle/cvd-widget"
Insert cell
import { changeTable } from "@ijlyttle/change-log"
Insert cell
import { inputMode, invokeMode, styleDark } from "@ijlyttle/dark-mode-input"
Insert cell
import { toSVG } from "@fil/plot-figure-to-svg"
Insert cell
viewof dark = inputMode({ value: false })
Insert cell
invokeMode(dark)
Insert cell
styleDark({ light: { background: "#fffff" }, dark: { background: "#262626" } })
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more