infodev
infodev

Reputation: 5235

Convert percentage to colors in javascript

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 ) enter image description here

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 )

enter image description here

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

Answers (1)

Muhammed B. Aydemir
Muhammed B. Aydemir

Reputation: 1015

UPDATE: You updated the question but the solution should be similar.

My solution would be as follows:

  1. Find the interval in which the value x is in-between (a,b = interval start and end)
  2. Get the colors for this interval (c1, c2)
  3. Find the gap for red green and blue values for c1 and c2 (ex. r_gap = r2-r1)
  4. Calculate 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

Related Questions