UNPKG

@thi.ng/color

Version:

Array-based color types, CSS parsing, conversions, transformations, declarative theme generation, gradients, presets

200 lines (199 loc) 4.64 kB
import { partial } from "@thi.ng/compose/partial"; import { TAU } from "@thi.ng/math/api"; import { clamp01 } from "@thi.ng/math/interval"; import { comp } from "@thi.ng/transducers/comp"; import { map } from "@thi.ng/transducers/map"; import { noop } from "@thi.ng/transducers/noop"; import { normRange } from "@thi.ng/transducers/norm-range"; import { push } from "@thi.ng/transducers/push"; import { transduce } from "@thi.ng/transducers/transduce"; import { tween } from "@thi.ng/transducers/tween"; import { zip } from "@thi.ng/transducers/zip"; import { setS4 } from "@thi.ng/vectors/sets"; import { clamp } from "./clamp.js"; const COSINE_GRADIENTS = { "blue-cyan": [ [0, 0.5, 0.5, 1], [0, 0.5, 0.5, 0], [0, 0.5, 0.3333, 0], [0, 0.5, 0.6666, 0] ], "blue-magenta-orange": [ [0.938, 0.328, 0.718, 1], [0.659, 0.438, 0.328, 0], [0.388, 0.388, 0.296, 0], [2.538, 2.478, 0.168, 0] ], "blue-white-red": [ [0.66, 0.56, 0.68, 1], [0.718, 0.438, 0.72, 0], [0.52, 0.8, 0.52, 0], [-0.43, -0.397, -0.083, 0] ], "cyan-magenta": [ [0.61, 0.498, 0.65, 1], [0.388, 0.498, 0.35, 0], [0.53, 0.498, 0.62, 0], [3.438, 3.012, 4.025, 0] ], "green-blue-orange": [ [0.892, 0.725, 0, 1], [0.878, 0.278, 0.725, 0], [0.332, 0.518, 0.545, 0], [2.44, 5.043, 0.732, 0] ], "green-cyan": [ [0, 0.5, 0.5, 1], [0, 0.5, 0.5, 0], [0, 0.3333, 0.5, 0], [0, 0.6666, 0.5, 0] ], "green-magenta": [ [0.6666, 0.5, 0.5, 1], [0.5, 0.6666, 0.5, 0], [0.6666, 0.666, 0.5, 0], [0.2, 0, 0.5, 0] ], "green-red": [ [0.5, 0.5, 0, 1], [0.5, 0.5, 0, 0], [0.5, 0.5, 0, 0], [0.5, 0, 0, 0] ], heat1: [ [0.5, 0.4, 0.25, 1], [0.5, 0.5, 0.666, 0], [0.5, 0.666, 0.8, 0], [0.5, 0.666, 0.8, 0] ], "magenta-green": [ [0.59, 0.811, 0.12, 1], [0.41, 0.392, 0.59, 0], [0.94, 0.548, 0.278, 0], [-4.242, -6.611, -4.045, 0] ], "orange-blue": [ [0.5, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 0], [0.8, 0.8, 0.5, 0], [0, 0.2, 0.5, 0] ], "orange-magenta-blue": [ [0.821, 0.328, 0.242, 1], [0.659, 0.481, 0.896, 0], [0.612, 0.34, 0.296, 0], [2.82, 3.026, -0.273, 0] ], "purple-orange-cyan": [ [0.5, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 0], [0.5, 0.5, 1, 0], [-0.25, 0.5, 1, 0] ], rainbow1: [ [0.5, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 0], [1, 1, 1, 0], [0, 0.3333, 0.6666, 0] ], rainbow2: [ [0.5, 0.5, 0.5, 1], [0.666, 0.666, 0.666, 0], [1, 1, 1, 0], [0, 0.3333, 0.6666, 0] ], rainbow3: [ [0.5, 0.5, 0.5, 1], [0.75, 0.75, 0.75, 0], [1, 1, 1, 0], [0, 0.3333, 0.6666, 0] ], rainbow4: [ [0.5, 0.5, 0.5, 1], [1, 1, 1, 0], [1, 1, 1, 0], [0, 0.3333, 0.6666, 0] ], "red-blue": [ [0.5, 0, 0.5, 1], [0.5, 0, 0.5, 0], [0.5, 0, 0.5, 0], [0, 0, 0.5, 0] ], "yellow-green-blue": [ [0.65, 0.5, 0.31, 1], [-0.65, 0.5, 0.6, 0], [0.333, 0.278, 0.278, 0], [0.66, 0, 0.667, 0] ], "yellow-magenta-cyan": [ [1, 0.5, 0.5, 1], [0.5, 0.5, 0.5, 0], [0.75, 1, 0.6666, 0], [0.8, 1, 0.3333, 0] ], "yellow-purple-magenta": [ [0.731, 1.098, 0.192, 1], [0.358, 1.09, 0.657, 0], [1.077, 0.36, 0.328, 0], [0.965, 2.265, 0.837, 0] ], "yellow-red": [ [0.5, 0.5, 0, 1], [0.5, 0.5, 0, 0], [0.1, 0.5, 0, 0], [0, 0, 0, 0] ] }; const cosineColor = (spec, t) => transduce( map( ([a, b, c, d]) => clamp01(a + b * Math.cos(TAU * (c * t + d))) ), push(), // @ts-ignore zip(...spec) ); const cosineGradient = (n, spec, tx) => transduce( comp(map(partial(cosineColor, spec)), tx ? map(tx) : noop()), push(), normRange(n - 1) ); const cosineGradientBuffer = (n, spec, buffer = [], offset = 0, cstride = 1, estride = 4) => { for (const t of normRange(n - 1)) { setS4(buffer, cosineColor(spec, t), offset, 0, cstride); offset += estride; } return buffer; }; const cosineCoeffs = (from, to) => { from = clamp([], from); to = clamp([], to); const amp = [...map(([a, b]) => 0.5 * (a - b), zip(from, to))]; return [ [...map(([s, a]) => s - a, zip(from, amp))], amp, [-0.5, -0.5, -0.5, -0.5], [0, 0, 0, 0] ]; }; const multiCosineGradient = (opts) => transduce( opts.tx ? map(opts.tx) : noop(), push(), tween({ num: opts.num, stops: opts.stops, easing: opts.easing, min: 0, max: 1, init: cosineCoeffs, mix: cosineColor }) ); export { COSINE_GRADIENTS, cosineCoeffs, cosineColor, cosineGradient, cosineGradientBuffer, multiCosineGradient };