@thi.ng/color
Version:
Array-based color types, CSS parsing, conversions, transformations, declarative theme generation, gradients, presets
200 lines (199 loc) • 4.64 kB
JavaScript
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": [
[],
[],
[],
[]
],
"blue-magenta-orange": [
[],
[],
[],
[]
],
"blue-white-red": [
[],
[],
[],
[-0.43, -0.397, -0.083, 0]
],
"cyan-magenta": [
[],
[],
[],
[]
],
"green-blue-orange": [
[],
[],
[],
[]
],
"green-cyan": [
[],
[],
[],
[]
],
"green-magenta": [
[],
[],
[],
[]
],
"green-red": [
[],
[],
[],
[]
],
heat1: [
[],
[],
[],
[]
],
"magenta-green": [
[],
[],
[],
[-4.242, -6.611, -4.045, 0]
],
"orange-blue": [
[],
[],
[],
[]
],
"orange-magenta-blue": [
[],
[],
[],
[]
],
"purple-orange-cyan": [
[],
[],
[],
[-0.25, 0.5, 1, 0]
],
rainbow1: [
[],
[],
[],
[]
],
rainbow2: [
[],
[],
[],
[]
],
rainbow3: [
[],
[],
[],
[]
],
rainbow4: [
[],
[],
[],
[]
],
"red-blue": [
[],
[],
[],
[]
],
"yellow-green-blue": [
[],
[-0.65, 0.5, 0.6, 0],
[],
[]
],
"yellow-magenta-cyan": [
[],
[],
[],
[]
],
"yellow-purple-magenta": [
[],
[],
[],
[]
],
"yellow-red": [
[],
[],
[],
[]
]
};
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 (let 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],
[]
];
};
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
};