refactor rainbow-quox scripting

This commit is contained in:
Rhiannon Morris 2025-01-01 00:40:20 +01:00
parent dff263856c
commit ddc36a9eea
10 changed files with 556 additions and 461 deletions

View file

@ -0,0 +1,120 @@
import * as R from '../rand.js';
import * as Color from './def.js';
const max = Math.max;
const min = Math.min;
export type State = R.State;
export type CloseFar = 'close' | 'far';
export type LightDark = 'light' | 'dark';
export class Rand extends R.Rand {
maxl: Color.Luma = 0.9;
minl: Color.Luma = 0.4;
minlLight: Color.Luma = 0.7;
maxlDark: Color.Luma = 0.65;
mincLight: Color.Chroma = 0.08;
maxcLight: Color.Chroma = 0.1;
mincDark: Color.Chroma = 0.12;
maxcDark: Color.Chroma = 0.175;
// max spread for a sequence of analogous colors. unless that would put them
// too close together
maxhWidth: Color.HueDistance = 80;
// minimum distance between adjacent analogous colors
minhSep: Color.HueDistance = 5;
// size of the wedge a "complementary" color can be in
maxhCompl: Color.HueDistance = 40;
// size of the wedge a "triadic" color can be in
maxhTriad: Color.HueDistance = 25;
constructor();
constructor([a, b, c, d]: State);
constructor(str: string);
constructor(st?: State | string) {
if (st === undefined) super();
else if (typeof st === 'string') super(st);
else super(st);
}
isLight(l: Color.Luma): boolean { return l >= this.minlLight; }
lightFor(baseL: Color.Luma, d: CloseFar = 'close'): Color.Luma {
const maxl = d == 'close' ? min(this.maxl, baseL * 1.25) : this.maxl;
return this.float(baseL, maxl);
}
darkFor(baseL: Color.Luma, d: CloseFar = 'close'): Color.Luma {
const minl = d == 'close' ? max(this.minl, baseL * 0.8) : this.minl
return this.float(minl, baseL);
}
brightFor(l: Color.Luma, baseC: Color.Chroma): Color.Chroma {
return this.float(baseC, this.isLight(l) ? this.maxcLight : this.maxcDark);
}
dullFor(l: Color.Luma, baseC: Color.Chroma): Color.Chroma {
return this.float(baseC, this.isLight(l) ? this.mincLight : this.mincDark);
}
analogous1(baseH: Color.Hue): Color.Hue {
const size = this.float(this.minhSep, 2 * this.minhSep);
return this.boolean() ? baseH + size : baseH - size;
}
analogous(baseH: Color.Hue, count: number): Color.Hue[] {
const minWidth = min(count * this.minhSep, this.maxhWidth * 0.8);
const width = this.float(minWidth, this.maxhWidth);
const sep = width / (count - 1);
const start = baseH - (width / 2);
const numbers = Array.from({length: count}, (_u, i) => start + i * sep);
return this.boolean() ? numbers : numbers.reverse();
}
complementary1(baseH: Color.Hue): Color.Hue {
return this.analogous1((baseH + 180) % 360);
}
complementary(baseH: Color.Hue, count: number): Color.Hue[] {
const angle = this.float(180 - this.maxhCompl/2, 180 + this.maxhCompl/2);
return this.analogous(baseH + angle, count);
}
triad(baseH: Color.Hue): [Color.Hue, Color.Hue] {
const angle = this.float(120 - this.maxhTriad/2, 120 + this.maxhTriad/2);
return [baseH - angle, baseH + angle];
}
baseLuma(ld?: LightDark): Color.Luma {
if (ld == 'light') {
return this.float(this.minlLight, this.maxl);
} else if (ld == 'dark') {
return this.float(this.minl, this.maxlDark);
} else {
return this.float(this.minl, this.maxl);
}
}
baseChroma(l: Color.Luma): Color.Chroma {
if (l >= this.minlLight) {
return this.float(this.mincLight, this.maxcLight);
} else {
return this.float(this.mincDark, this.maxcDark);
}
}
baseHue(): Color.Hue { return this.float(360); }
color(ld?: LightDark): Color.Color {
const l = this.baseLuma(ld);
const c = this.baseChroma(l);
const h = this.baseHue();
return Color.oklch(l, c, h);
}
}