Public
Edited
Nov 19, 2022
Importers
5 stars
Insert cell
Insert cell
rgb = (r,g,b,a=255,convert=degamma) => [
convert(r/255),
convert(def(g,r)/255),
convert(def(b,g,r)/255)
]
Insert cell
Insert cell
grey = _ => rgb(lerp(0,255,_))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
hue = ([r,g,b]) =>
(60/360) * (
(r >= g && g >= b) ? 0 + (g-b)/((r-b)||1)
: (g >= r && r >= b) ? 2 - (r-b)/((g-b)||1)
: (g >= b && b >= r) ? 2 + (b-r)/((g-r)||1)
: (b >= g && g >= r) ? 4 - (g-r)/((b-r)||1)
: (b >= r && r >= g) ? 4 + (r-g)/((b-g)||1)
: /*(r >= b && b >= g) ?*/ 6 - (b-g)/((r-g)||1)
)

Insert cell
saturation = (rgb) => {
const [mn, mx] = minmax(rgb);
const l = (mx + mn) / 2;
const s = mx - mn;
return s
? (l < 0.5
? s / (mx + mn)
: s / (2 - mx - mn))
: (l > 0 && l < 1
? 0
: NaN)
}
Insert cell
luminosity = ([r,g,b]) =>
(max(r,g,b) + min(r,g,b)) / 2
Insert cell
Insert cell
Insert cell
Insert cell
luminance = ([r,g,b]) => 0.2126*r + 0.7152*g + 0.0722*b
Insert cell
Insert cell
luma = ([r,g,b]) => 0.212*gamma(r) + 0.7152*gamma(g) + 0.0722*gamma(b)
Insert cell
Insert cell
lightness = (rgb)=>{
// This is from: https://stackoverflow.com/a/56678483/4100249
const y = luminance(rgb)
return (y <= (216/24389) ? y * (24389/27) : Math.pow(y,(1/3)) * 116 - 16) / 100.0
}
Insert cell
Insert cell
contrast = (c0,c1) => {
const [l2, l1] = minmax(luminance(c0), luminance(c1))
return (l1 + 0.05) / (l2 + 0.05)
}
Insert cell
Insert cell
colordist = ([r0,g0,b0],[r1,g1,b1]) =>
// Note: 1.7320508075688772 is the maximum distance (Math.sqrt(3))
Math.sqrt( (r1-r0)*(r1-r0) + (g1-g0)*(g1-g0) + (b1-b0)*(b1-b0)) / 1.7320508075688772

Insert cell
Insert cell
perdist =([r0,g0,b0],[r1,g1,b1]) => {
// NOTE: No need to degamma here as the article mentions that the formula is fore non-linear sRGB
const dr = gamma(r0 - r1);
const dg = gamma(g0 - g1);
const db = gamma(b0 - b1);
return Math.abs(dr) < 128
? Math.sqrt((2*dr*dr + 4*dg*dg + 3*db*db)/3)
: Math.sqrt((3*dr*dr + 4*dg*dg + 2*db*db)/3)}
Insert cell
md`The tint distance returns the tint factor *k* that can be used to bring the color closer to the target colour by tinting it to black or white`
Insert cell
tintdist = (color,target) => {
const [rs,gs,bs] = color;
const [rt,gt,bt] = target;
// TODO: We should make the target tints optional
const drm = 1.0 - rs;
const dgm = 1.0 - gs;
const dbm = 1.0 - bs;
const kr = clamp((rt-rs) / drm, -1, 1);
const kg = clamp((gt-gs) / dgm, -1, 1);
const kb = clamp((bt-bs) / dbm, -1, 1);
return (kr + kg + kb) / 3;
}
Insert cell
Insert cell
Insert cell
degamma = asMappable(_ =>
_ <= 0.03928 ? _/12.92 : Math.pow( ( _ + 0.055) / 1.055, 2.4))
Insert cell
gamma = asMappable(_ =>
_ <= 0.003040 ? _ * 12.92 : 1.055 * Math.pow(_, 1.0/2.4) - 0.055)
Insert cell
Insert cell
tint = (color,k,to=[1,1,1]) =>
blend(to,color,k)
Insert cell
Insert cell
tintWithLuminance = (color, l) => {
const v = luminance(color);
return l < v ? tint(color, prel(l, 0, v), [0,0,0]) : tint(color, prel(l, 1, v));
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

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