Reputation: 79
I'm writing a Javascript code and I want to implement a color meter.
I need to write a function that takes a int between i - j, and based on how high that number is, it will return a color between #CCCCCC (i on the scale) and #3B5998 (j on the scale).
Similar to how this work:
Upvotes: 3
Views: 227
Reputation: 36995
Alternative solution using HSL color model, which is better suited for this sort of things. The ingredients of a HSL are: Hue, Saturation and Lightness.
You have two colors: #3B5998
== hsl(221, 40%, 41%)
, and
#cccccc
== hsl(221, 0%, 80%)
(since it's 0% saturation the hue doesn't matter here).
Now you only need a way to convert the integer value in the range between min and max to percentage and apply this percentage to Saturation (0..40) and Lightness (41..80).
const scale = ( min, max, number) => (( number - min ) / ( max - min ));
Given minimum, maximum value and a number returns where the number falls on a scale from 0 to 1, e.g. scale( 0, 100, 50 ) === 0.5
const range = ( min, max, percentage ) => ( min + (max - min) * percentage );
Given minimum, maximum value and percentage return the number on the percentage point between min and max, e.g. range( 0, 100, 0.5 ) === 50
.
To saturate and lighten the color you need to calculate the S and L values given the point on scale and min/max values. The color object used in examples is in the format { h:221, s :0, l:0 }
const colorTween = ( colorA, colorB, percentage ) => ({
h : range( colorA.h, colorB.h, percentage ) | 0,
s : range( colorA.s, colorB.s, percentage ) | 0,
l : range( colorA.l, colorB.l, percentage ) | 0
});
The colorTween
function takes two colors and applies the percentage of difference between min and max to the difference between h, s, and l of these two colors.
const getColor = ( number, min, max ) => {
const percentage = scale( min, max, number );
return colorTween({ h: 221, s:0, l:80}, { h: 221, s:40, l:41 }, percentage)
}
In action: https://jsfiddle.net/tbcwwrgr/
In your case hue is constant, but you could also make a "rainbow" scale using colorTween({ h: 0, s:100, l:50}, { h: 255, s:100, l:50 }, percentage)
Upvotes: 2
Reputation: 386848
You could use the delta of the colors and divide by the wanted range (minus one) and multiply for the given position. Then convert back to a hex value.
function getColor(i, left, right) {
function c(c0, c1) {
return ('00' + Math.floor(
parseInt(c0, 16) * (right - i) / (right - left) +
parseInt(c1, 16) * (i - left) / (right - left)
).toString(16)).slice(-2);
}
return c(color[0].slice(0, 2), color[1].slice(0, 2)) + c(color[0].slice(2, 4), color[1].slice(2, 4)) + c(color[0].slice(4, 6), color[1].slice(4, 6));
}
var color = ['CCCCCC', '3B5998'],
min = 4000,
max = 40902,
span, i, v;
span = document.createElement('span');
span.innerHTML = min + ' '
document.body.appendChild(span);
for (i = min; i <= max; i += (max - min) / 68) {
v = getColor(i, min, max);
span = document.createElement('span');
span.innerHTML = ' ';
span.style.backgroundColor = '#' + v;
span.title = 'i: ' + Math.floor(i) + '\n#' + v;
document.body.appendChild(span);
}
span = document.createElement('span');
span.innerHTML = ' ' + max;
document.body.appendChild(span);
Upvotes: 3
Reputation: 3541
I have created a code where you input a number and according to value the output box shows the hex color value between the two given range.Fiddle
Here is the code
document.getElementById("clickMe").onclick = function() {
var inp = document.getElementById("myInput").value;
var start = 0x3B5998,
end = 0xcccccc,
myResult;
var cnt = 0;
var intervalId = setInterval(function() {
if (start == end) {
clearInterval(intervalId)
};
myResult = (start).toString(16);
if (myResult.length < 8) {
myResult = "0000000".substring(0, 8 - myResult.length) + myResult;
}
cnt++;
start++;
if (inp == cnt) {
document.getElementById("result").value = myResult;
console.log(myResult);
clearInterval(intervalId);
}
}, 1);
}
<input type="number" id="myInput" placeholder="enter a number" />
<button id="clickMe" onclick="myFunction()">
CLICK TO FIND HEX VALUE
</button>
<input type="text" id="result" />
Upvotes: 1
Reputation: 36987
function getColor(i, j, n) {
var r = 0xCC-Math.round((0xCC-0x3b)*(j-n)/(j-i));
var g = 0xCC-Math.round((0xCC-0x59)*(j-n)/(j-i));
var b = 0xCC-Math.round((0xCC-0x98)*(j-n)/(j-i));
// not really necessary for your color selection, included for completeness
var twoDigits=function(s) {
if (s.length==1) return "0"+s;
return s;
}
return "#"+
twoDigits(r.toString(16))+
twoDigits(g.toString(16))+
twoDigits(b.toString(16));
}
Upvotes: 1
Reputation: 6707
A naive method would be to take start and end values for both colors, calculate a percentage from the startpoint and get the difference, then convert back to hex. I converted your colors #CCCCCC
and #3B5998
to their RGB values, passed them to a function which does this and, using code from this fiddle, I converted them to hex values. You can see the results below:
//Function to convert hex format to a rgb color
function rgb2hex(rgb) {
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
return (rgb && rgb.length === 4) ? "#" +
("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2], 10).toString(16)).slice(-2) +
("0" + parseInt(rgb[3], 10).toString(16)).slice(-2) : '';
}
function getGradientColor(startColorRed, startColorGreen, startColorBlue, endColorRed, endColorGreen, endColorBlue, gradientSize, gradientPoint) {
var diffRed = endColorRed - startColorRed;
var diffGreen = endColorGreen - startColorGreen;
var diffBlue = endColorBlue - startColorBlue;
diffRed = (diffRed * gradientPoint / gradientSize) + startColorRed;
diffGreen = (diffGreen * gradientPoint / gradientSize) + startColorGreen;
diffBlue = (diffBlue * gradientPoint / gradientSize) + startColorBlue;
return rgb2hex('rgba(' + parseInt(diffRed) + ',' + parseInt(diffGreen) + ',' + parseInt(diffBlue) + ')');
}
var startColorRed = 204;
var startColorGreen = 204;
var startColorBlue = 204;
var endColorRed = 59;
var endColorGreen = 89;
var endColorBlue = 152;
console.log(getGradientColor(startColorRed, startColorGreen, startColorBlue, endColorRed, endColorGreen, endColorBlue, 1000, 0));
console.log(getGradientColor(startColorRed, startColorGreen, startColorBlue, endColorRed, endColorGreen, endColorBlue, 1000, 510));
console.log(getGradientColor(startColorRed, startColorGreen, startColorBlue, endColorRed, endColorGreen, endColorBlue, 1000, 1000));
Upvotes: 1