Reputation: 5235
I would like to generate color according to value from -1 to 1
the base colors are
My gaps are H:0 =1, H:60 = 0.5 , H:170= 0, H:200= -1 ( S:100 and L:50 )
I have found an example that convert percentage from green to red.
function percentageToColor(percentage, maxHue = 200, minHue = 0) {
const hue = percentage * (maxHue - minHue) + minHue;
return `hsl(${hue}, 100%, 50%)`;
}
I would like to adapt it to my case by adding blue and use values from -1 to 1 by respecting the gaps equivalences as I mentioned above but I don't see how to do it.
Upate
I would like to use HSL/HSV
I'm looking for a way to find relation between percentage and H
value
Update 2
I have Implemented @Muhammed B. Aydemir solution but visually I get colors ouf of the spectrum ( eventually black )
percentageToColor(pourcentage) {
let x = pourcentage.toFixed(2);
const colors = [[4, 189, 237], [10, 19, 0], [255, 248, 3], [253, 45, 45]];
const range = [0, 1, 1.5, 2];
const inBetween = (x, a, b) => x >= a && x <= b;
for (let i = 0; i < range.length; i++) {
const m = range[i];
const n = range[i + 1];
console.log(inBetween(x, m, n));
if (inBetween(x, m, n)) {
const c1 = colors[i];
const c2 = colors[i + 1];
const rangeDiff = n - m;
const ratio = Math.abs((x - m) / rangeDiff);
const [r, g, b] = c1.map((e, i) => {
const e1 = c1[i];
const e2 = c2[i];
return Math.round(e1 + (e2 - e1) * ratio);
});
let color = [r, g, b].reduce((p, c) => `${p}${c.toString(16).padStart(2, '0')}`, '#');
console.log([x, color]);
return color;
} else if (x > range[range.length - 1]) {
console.log(x + 'red');
return 'red';
}
}
return 'OUT OF RANGE';
}
Upvotes: 1
Views: 327
Reputation: 1015
UPDATE: You updated the question but the solution should be similar.
My solution would be as follows:
(a,b = interval start and end)
(c1, c2)
(ex. r_gap = r2-r1)
r = r1 + r_gap * |x - a / interval_length|
And you should have your r,g,b
values.
Example:
const colors = [[4, 189, 237], [99, 19, 0], [255, 248, 3], [253, 45, 45]]
const range = [-1, 0, 0.5, 1]
const inBetween = (x, a, b) => x >= a && x <= b
const toRGB = x => {
for (let i = 0; i < range.length; i++) {
const m = range[i]
const n = range[i + 1]
if (inBetween(x, m, n)) {
const c1 = colors[i]
const c2 = colors[i + 1]
const rangeDiff = n - m
const ratio = Math.abs((x - m) / rangeDiff)
const [r, g, b] = c1.map((e, i) => {
const e1 = c1[i]
const e2 = c2[i]
return Math.round(e1 + (e2 - e1) * ratio)
})
console.log(r, g, b)
return [r, g, b].reduce((p, c) => `${p}${c.toString(16).padStart(2, '0')}`, '#')
}
}
if (x < range[0]) return 'white' // below range
return 'red' // above range
}
const element = document.createElement('div');
let linearGradient = ''
for (let i = range[0]; i < range[range.length - 1]; i += 0.01)
linearGradient += toRGB(i) + ','
element.style.backgroundImage = `linear-gradient(to right,${linearGradient}${toRGB(range[range.length -1])})`;
document.body.append(element);
div {
width: 500px;
height: 40px;
float: left;
}
Upvotes: 2