I have a few handy, seen in folk’s patterns or ported from plain JS:
//linear interpolation
function lerp(a, b, t) {
return a * (1-t) + b * t
}
//cross fade RGB between 2 colors using linear interpolation
//output sets r,g,b globals
function crossFadeColors(r1, g1, b1, r2, g2, b2, t) {
r = lerp(r1, r2, t)
g = lerp(g1, g2, t)
b = lerp(b1, b2, t)
}
//convert HSV to RGB
//output sets r,g,b globals
function hsv2rgb(hh, ss, vv) {
var h = mod(hh, 1)
var s = clamp(ss, 0, 1)
var v = clamp(vv, 0, 1)
var i = floor(h * 6)
var f = h * 6 - i
var p = v * (1 - s)
var q = v * (1 - (s * f))
var t = v * (1 - (s * (1 - f)))
if (i == 0) {
r = v; g = t; b = p
} else if (i == 1) {
r = q; g = v; b = p
} else if (i == 2) {
r = p; g = v; b = t
} else if (i == 3) {
r = p; g = q; b = v
} else if (i == 4) {
r = t; g = p; b = v
} else if (i == 5) {
r = v; g = p; b = q
}
}
//convert HSL to RGB
//output sets r,g,b globals
function hsl2rgb(h,s,l){
value = s * min(l,1-l) + l
sat2 = value ? 2-(2*l/value) : 0
hsv2rgb(h,sat2,value);
}
//convert RGB to HSV
//output sets h,s,v globals
function rgb2hsv(r, g, b) {
var rr, gg, bb, diff
r = clamp(r, 0, 1)
g = clamp(g, 0, 1)
b = clamp(b, 0, 1)
v = max(r, max(g, b))
diff = v - min(r, min(g, b))
if (diff == 0) {
h = s = 0
} else {
s = diff / v
rr = (v - r) / 6 / diff
gg = (v - g) / 6 / diff
bb = (v - b) / 6 / diff
if (r == v) {
h = bb - gg
} else if (g == v) {
h = (1 / 3) + rr - bb
} else if (b == v) {
h = (2 / 3) + gg - rr
}
if (h < 0) {
h += 1
} else if (h > 1) {
h -= 1
}
}
}
(some could use slight tweaks/optimizations)
I’m considering these for inclusion in the API, but I want to figure out a good way to handle color “types”, and obviously wouldn’t be setting globals as a way of returning values.