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
"Scroll" to the Very Right of a Long Text Input
IE9: Why Setting "-Ms-Transform" Works from CSS, But Not with Jquery.Css()
How to Change Reactjs Styles Dynamically
Jquery CSS Rendering - Works in Firefox, Not in Chrome
How to Raw Url Encode/Decode in JavaScript and Ruby to Get the Same Values in Both
How to Get JavaScript Caller Function Line Number and Caller Source Url
How to Replace All Dots in a String Using JavaScript
Internal API Fetch with Getserversideprops? (Next.Js)
Difference Between Single Quotes and Double Quotes in JavaScript
JavaScript Promises - Reject VS. Throw
JavaScript Detect Click Event Outside of Div
Bootstrap and Jqueryui Conflict
How to Detect CSS Flex Wrap Event
External CSS Styles Cant Be Accessed in Google Chrome
Difference Between Statement and Function
Why Is String Concatenation Faster Than Array Join
Create an Array with Same Element Repeated Multiple Times
Why Is the Domsubtreemodified Event Deprecated in Dom Level 3