How to Get Color Value from Gradient by Percentage with JavaScript

How to get color value from gradient by percentage with javascript?

I was able to solve this issue using this function, which is based on the less.js function: http://lesscss.org/functions/#color-operations-mix

function pickHex(color1, color2, weight) {
var w1 = weight;
var w2 = 1 - w1;
var rgb = [Math.round(color1[0] * w1 + color2[0] * w2),
Math.round(color1[1] * w1 + color2[1] * w2),
Math.round(color1[2] * w1 + color2[2] * w2)];
return rgb;
}

I just simply need to pass the two closest color codes from the gradient array and the ratio where the slider handle is located(which can be calculated easily with the help of the slider width). Here is the live example:

http://jsfiddle.net/vksn3yLL/

from green to red color depend on percentage

This may be more than you need, but this lets you set up any arbitrary color map:

var percentColors = [
{ pct: 0.0, color: { r: 0xff, g: 0x00, b: 0 } },
{ pct: 0.5, color: { r: 0xff, g: 0xff, b: 0 } },
{ pct: 1.0, color: { r: 0x00, g: 0xff, b: 0 } } ];

var getColorForPercentage = function(pct) {
for (var i = 1; i < percentColors.length - 1; i++) {
if (pct < percentColors[i].pct) {
break;
}
}
var lower = percentColors[i - 1];
var upper = percentColors[i];
var range = upper.pct - lower.pct;
var rangePct = (pct - lower.pct) / range;
var pctLower = 1 - rangePct;
var pctUpper = rangePct;
var color = {
r: Math.floor(lower.color.r * pctLower + upper.color.r * pctUpper),
g: Math.floor(lower.color.g * pctLower + upper.color.g * pctUpper),
b: Math.floor(lower.color.b * pctLower + upper.color.b * pctUpper)
};
return 'rgb(' + [color.r, color.g, color.b].join(',') + ')';
// or output as hex if preferred
};

Get colors values from percentages

Calculate the red aspect and blue aspect of RGB based on the percentage you get, then insert them to your rgb value.

Here's a working example:

window.onload = function() {  let colorShower = document.querySelector('.color-shower')  let colorSlider = document.querySelector('#colorSlider')  let blueAspect = percentage => Math.round(255 * (1 - (percentage - 1) / 200))  let redAspect = percentage => Math.round(255 * (percentage - 1) / 200)  let percentage = colorSlider.value  let buildColor = (redAspect, blueAspect) => `rgb(${redAspect}, 0, ${blueAspect}`      colorShower.style.backgroundColor = buildColor(redAspect(percentage), blueAspect(percentage))    colorSlider.addEventListener('input', e => {    percentage = colorSlider.value    colorShower.style.backgroundColor = buildColor(redAspect(percentage), blueAspect(percentage))  })}
.color-shower {  width: 100%;  height: 50px;}
.color-slider { width: 100%;}
<div class = "color-shower"></div><input type = "range" min = "1" max = "200" value = "1" class = "color-slider" id = "colorSlider">

Calculate color HEX having 2 colors and percent/position

This should work:

It basically involves converting them to decimal, finding the halves, converting the results back to hex and then concatenating them.

var color1 = 'FF0000';
var color2 = '00FF00';
var ratio = 0.5;
var hex = function(x) {
x = x.toString(16);
return (x.length == 1) ? '0' + x : x;
};

var r = Math.ceil(parseInt(color1.substring(0,2), 16) * ratio + parseInt(color2.substring(0,2), 16) * (1-ratio));
var g = Math.ceil(parseInt(color1.substring(2,4), 16) * ratio + parseInt(color2.substring(2,4), 16) * (1-ratio));
var b = Math.ceil(parseInt(color1.substring(4,6), 16) * ratio + parseInt(color2.substring(4,6), 16) * (1-ratio));

var middle = hex(r) + hex(g) + hex(b);

How to deduce the relative percentage value of a color using a color gradient

Well that was a lot easier than I thought it would be. I was able to find existing code or tools that took care of the hard parts.

In case anyone wants to know how I did it, first I generated a color gradient of 51 colors from #FFFFFF to #E75800 (using this tool). Stored these in an object with keys 0 to 100 (to represent the percentage), skipping every other digit, like so:

var colors = {
0: "FFFFFF", 2: "FEFBF9", 4: "FEF8F4", 6: "FDF4EF", 8: "FDF1EA",
10: "FCEEE5", 12: "FCEAE0", 14: "FBE7DB" // Truncated...
}

Note: You don't need to skip every other digit. I just did that because the took I linked to only allows up to 63 colors to be generated at once (yes, I know I could just run it multiple times)

Then borrowing the getSimilarColors function from this SO post, find the closest match by comparing the provided color to the values within the object created earlier. The key of the element that was a closest match would be the percent.

Thanks.

Find the RGB colour value at a specific percentage of a four stop gradient

You could use the delta of the interval of the steps and calculate the color with the right ratio.

How it works.

For example we are looking for the color of 70 % and first, we get the interval of

[66, 100]

Then build the ratio by

  • the delta of percent and the left interval (left)

      70 - 66 => 4
  • the delta of the right interval and percent (right)

      100 - 70 => 30
  • delta of right and left interval (delta)

      100 - 66 => 34
  • with the above generated ratios, it is possible to calculate the right color inbetween of two colors with the parts.

      (color of left interval * right + color of right interval * left) / delta => color

Repeat the last step for all colors and return the result.

Working example:

* denotes given colors, hover shows percent value and RGB value.

function getColor(percent) {
function getInterval(range) {
function getRatio(color) {
return Math.floor((colors[range[0]][color] * right + colors[range[1]][color] * left) / delta);
}

var left = percent - range[0],
right = range[1] - percent,
delta = range[1] - range[0];

return { r: getRatio('r'), g: getRatio('g'), b: getRatio('b') };
}

return colors[percent] || getInterval(stops.reduce(function (r, a, i, aa) {
return a < percent ? [a, aa[i + 1]] : r;
}, [0, 0]));
}

var stops = [0, 33, 66, 100],
colors = { 0: { r: 25, g: 47, b: 97 }, 33: { r: 75, g: 183, b: 183 }, 66: { r: 237, g: 120, b: 87 }, 100: { r: 209, g: 74, b: 88 } },
i, color, rgb;

for (i = 0; i <= 100; i++) {
color = getColor(i),
rgb = ['r', 'g', 'b'].map(function (k) { return color[k]; });
document.body.innerHTML += '<span style="color: #fff; background-color: rgb(' + rgb + ');" title="' + (colors[i] ? '* ' : '') + i + ' % rgb(' + rgb.join(', ') + ')">' + (colors[i] ? '* ' : '  ') + '</span>';
}

Get color value of specific position in colorbar with gradient

I chose to implement your first solution (figure out the gradient with JavaScript). It means you don't need to rely on support for the canvas element, which may be important depending on your browser support.

Using the canvas methods would also be cool, and easier. You could render the color stops from the CSS, and then use getImageData() to figure out which color the pointer was over.

You can extract the CSS colours with a regex, and map any human ones to RGB with...

var background = window.getComputedStyle(element).getPropertyValue("background");

var colorStops = [];
var matchColorStops = /,\s*(\w+)\s+(\d+)%/g;
var match;

var humanToHex = {
"red": [255, 0, 0],
"green": [0, 128, 0],
"blue": [0, 0, 255]
};

while (match = matchColorStops.exec(background)) {
if (humanToHex[match[1]]) {
match[1] = humanToHex[match[1]];
}
colorStops.push({
percentage: match[2],
color: match[1]
});
}

You can use this small JavaScript function to interpolate two colours if they are separated into their RGB values.

var getStepColor = function(colorA, colorB, value) {
return colorA.map(function(color, i) {
return (color + value * (colorB[i] - color)) & 255;
});
};

You can combine that to get some code that will let you do this...

var getStepColor = function (colorA, colorB, value) {
return colorA.map(function (color, i) {
return (color + value * (colorB[i] - color)) & 255;
});
};

var gradient = document.querySelector("#gradient");
var preview = document.querySelector("#preview");

var background = window.getComputedStyle(gradient).getPropertyValue("background");

var colorStops = [];
var matchColorStops = /,\s*(\w+)\s+(\d+)%/g;
var match;

var humanToHex = {
"red": [255, 0, 0],
"green": [0, 128, 0],
"blue": [0, 0, 255]
};

while (match = matchColorStops.exec(background)) {
// If colour is *human-readable*, then
// substitute it for a RGB value.
if (humanToHex[match[1]]) {
match[1] = humanToHex[match[1]];
}
colorStops.push({
percentage: match[2],
color: match[1]
});
}

gradient.addEventListener("mousemove", function (event) {

var x = event.pageX - gradient.offsetTop;
var y = event.pageY - gradient.offsetLeft;
var percentage = (x / this.offsetWidth) * 100;

var i;
for (i = 0; i < colorStops.length; i++) {
if (colorStops[i].percentage > percentage) {
break;
};
}

var lowerIndex = i == 1 ? 0 : i - 1;
var upperIndex = lowerIndex + 1;
var value = x / (gradient.offsetWidth / (colorStops.length - 1)) % 1;

color = getStepColor(colorStops[lowerIndex].color, colorStops[upperIndex].color, value);

preview.style.backgroundColor = "rgb(" + color.join() + ")";
preview.textContent = preview.style.backgroundColor;

});

jsFiddle.

This is just a quick hack-ish way to come up with this, there is probably a better foolproof method of extracting the colors, and for figuring out where the pointer is in relation to which gradient segment.



Related Topics



Leave a reply



Submit