Comparing two colors to get likeness rating - javascript

I have a color selector that allows a user to change fore and background color for a grid. I wondered if there is a way to compare two colors in the #FFFFFF format to get a "likeness" rating, i.e. to try and verify if the foreground colors are readable on a specified background.

If colour_1 = #aabbcc and colour_2 = #AABBCC you could do something like:
diff = sqrt((aa - AA)^2 + (bb - BB)^2 + (cc - CC)^2)
The smaller this value is, the more alike the two colours should be.

Related

Sorting Colours Using Delta-E

I would like to sort a set of colours so that I can display them in the most visually pleasing way. I understand that this is a wide topic and what is deemed as visually pleasing is open to debate, so I have chosen to use the Delta-E algorithm. I am using a JS library called Delta-E.
I can use this algorithm to compare two colours at a time and find the perceived difference between them and it is trivial to run through all colour combinations and store this difference for each combination.
However I am unsure how to proceed beyond this point. Once I have deltas for each pair of colours how do I use these values to order the colours?
What kind of sort do I need to use?
I'm actually dealing with the same problem right now. One solution I am tinkering with is to set an anchor color. What I mean by that is that you'd call your deltaE function with the same anchor color and then the color you wish to compare, which will return the difference values from the same color. You can then use that difference value in your Array.sort() call:
const colors = ['#333333', '#f1f1f1', '#00aacc', '#ff6666', '#000000'];
const anchorColor = '#fff'; // White or black might be a decent choice of anchor color
colors.sort((colorA, colorB) => {
// For each color, determine the color difference FROM the anchor color (not each other)
const colorADelta = deltaE(anchorColor, colorA);
const colorBDelta = deltaE(anchorColor, colorB);
if (colorADelta > colorBDelta) {
return 1;
}
if (colorADelta < colorBDelta) {
return -1;
}
return 0;
});
However, in my personal testing, I've found that the deltaE difference values weren't exactly right for this anchor technique, and I instead used the Euclidean distance as the value, from this library (which also has a Delta-E function).

Get the ranges and color associated with it - Chroma.js

I've a certain requirement where in user will input the color and the values.
I'm using chroma.js, say for example
var scale = chroma.scale(['color1','color2','color3']).domain([0,3,10,80,100]);
So now I've 3 user defined color and muliple values. I'm using the chroma.js to get the color out of it for the particular value.
scale(10).hex() // Will give me a #color
My Question is, I need something like
0 - 30 = color1
30 - 65 = color2
65 - 100 = color3
Please help me how to achieve this using chroma.js. Hope my question is clear.
I think scale.classes is exactly what you want:
chroma.scale(['red','blue','green'])
.domain([0,100])
.classes([0,33,65,100])

trying to make gradient using boxes

I need to know how can I specify some variable parameters to my background color??
I'm trying to use JavaScript and i want to make this shape :
I know the parameters,
My approach was to take the initial division, append a child division to it with smaller size and different background color..
However, for this to work i needed to use this : box[i].style.backgroundColor = "rgb(255-10*i, 255-10*i, 255-10*i)"
Which didnt work, And i was told that the rgb only takes integers parameters, so i tried to do this:
color = 255-10*i;
box[i].style.backgroundColor = "rgb(color,color,color)";
which led to the same error.. Any idea how to proceed?
Note: 1- I'm using that code in a for loop to create say 20 nested division with different color and size
2- I'm obliged to do it using javascript with no manipulation with neither html nor css files...
3- I need it as fast as possible( Studying for the exam )
Any help is appreciated..
you need to concatenate the string with the value of color. right now you're just making a string with the word color inside it:
color = 255-10*i;
box[i].style.backgroundColor = "rgb(" + color + "," + color + "," + color + ")";
You are passing the variables as strings
box[i].style.backgroundColor = "rgb(color,color,color)";
Should be
box[i].style.backgroundColor = "rgb("+color+","+color+","+color+")";

Set background color based on outdoor temperature

Heyoh SO,
I have a temperature widget to implement on a project I am working on.
Nothing is specially difficult, I've got a free API to retrieve the datas that I need ect.
BUT, the lovely designer who works with me would have a color feature for which I've got no good idea to start with...
He would to define a background-color depending on the current weather temperature.
I mean if the temperature is cold, like -20, the background color should be blue / violet / any cold color; and when it's warm, like 25, it should have a hot background-color like orange / red.
I think I could easily work with an array of "temperature steps", but I would prefer to work with a function that could define the color depending of the temperature. I know it's strange, I don't know if there is an algorithm to define a color by it's temperature color...
This article is helpfull http://en.wikipedia.org/wiki/Color_temperature but quite complicated, if someone has any idea, even for a beginning, I am very interested !
I saw this thread:
Display temperature as a color with C#?
But I'm not using C# and I don't want to, so if there is a solution in JavaScript, it would be perfect. I can eventually work with PHP or NodeJS if there is a server-side need.
EDIT - Answer:
Finally, I didn't have the choice to use a real colors gradient array, because of the graphic needs.
But I still had to mix the colors of the closest steps depending of the temperature !
I wrote a small JS library to do that, that you will be able to find on GitHub soon, I'll post the link here.
You can find it here:
The presentation website of the project
Or the github project
Your colour range looks to be the same as a "hue-only" sweep in "HSL colour space" from 270º (violetish) at -30ºC down to 30º (orange) at +30ºC
var hue = 30 + 240 * (30 - t) / 60;
If t is out of range, either clamp it before calling the above expression, or clamp h to the desired hue range afterwards.
On supported browsers you can use an hsl(h, s, l) colour string, or use commonly available "HSL to RGB" functions to convert the HSL colour into RGB.
See http://jsfiddle.net/V5HyL/
This is a special-case, not a generic solution, but by simply doing a linear gradient between hues and scrunching the blend in the middle range (i.e. the green) you can get a reasonable approximation without color stepping:
Demo: http://jsfiddle.net/bcronin/kGqbR/18/
//
// Function to map a -30 to 30 degree temperature to
// a color
//
var F = function(t)
{
// Map the temperature to a 0-1 range
var a = (t + 30)/60;
a = (a < 0) ? 0 : ((a > 1) ? 1 : a);
// Scrunch the green/cyan range in the middle
var sign = (a < .5) ? -1 : 1;
a = sign * Math.pow(2 * Math.abs(a - .5), .35)/2 + .5;
// Linear interpolation between the cold and hot
var h0 = 259;
var h1 = 12;
var h = (h0) * (1 - a) + (h1) * (a);
return pusher.color("hsv", h, 75, 90).hex6();
};
The wikipedia article on color temperature is not connected to your problem. The wikipedia article is only relevant for digital imaging experts. Color temperature in this context means something different ...
Your problem is about how to visualize a certain temperature in degrees celsius. There is no standard algorithm to do this. It's up to the designer how to solve this task.
I would probably build an array of rgb-values for every 2.5°C or 5°C and then blend by rgb for the temperature values in between.
I recently had this conundrum with using time data to display the colors of the sky that that time would correspond to. It's tough, Here are three ways I explored:
1) The bad-ass way: Make a function for your R, G, B channels separately that would accept an x-intercept of your temperature, and spit out a y-intercept for your Red channel, Blue channel and Green channel over the range of temperatures and corresponding colors you have. To make this I would reverse engineer it by sampling along the color range for some major division of the temperatures and plotting as many points as you can and then drawing a 6th degree polynomial through the points for each of the channels. You would get a function which could accept a temperature value and combine 3 outputs for the R, G, and B channels of an RGB color for alpha 1. Should work, haven't tested it though and am not willing to haha
2) Make a background class for each of the major colors (you decided whether this is 5 or 50 colors) and toggle between them with an alpha blend. This is what I ended up using for my issue.
if(temp > 0 && temp <= 5)
{
greenBackground.alpha == 1
yellowBakckground.alpha == (temp/5)
}
else if(temp > 5 && temp <= 10)
etc...
So if your temp was 2.5 then it would be 50% mix of yellow and green
I was able to implement this option in 1 night and the result looks great! It's time consuming, but do-able and not as messy as you might think.
3) Make and store an array with RGB colors sampled from your gradient against all the possible integers (there aren't that many between -30 and 30) and round the API's data to integer values if needed. That would be the simplest I suppose. Definitely not as cool as Option 1 though :)
Good luck!

Specifically translating data into colors in D3.js

I have just started with D3.js, and I'm reading through this: http://alignedleft.com/tutorials/d3
In the section on creating a bar chart, the author gives a very simple example of using the current data in the loop to specify the RGB value of the rectangle's fill color. That's very useful. But is rather limited.
Say, for instance - I had a specific type of graph that shows various priorities of data. So, the higher the value, the higher the priority. The priority would be visualized with red, orange, yellow and green colors for high, medium, low, none, respectively.
It's fairly simple to do using a switch case or an if/else in the .attr('fill', function(d){})method, like so:
.attr('fill', function(d) {
if (percentage(d) <= 0.25) { // 0.25 is a percentage value representing the data
return 'green';
}
else if (percentage(d) <= 0.50) {
return 'yellow';
}
else if (percentage(d) <= 0.75) {
return 'orange';
}
else if (percentage(d) <= 1) {
return 'red';
}
});
But what if I wanted to dynamically change the intensity/shade of the colour itself based on the intensity of the data? So not only would it have basic color values, but visualize the intensity of the data within that colour range by making the colour a different shade (or saturation) depending on the intensity of data before shifting to the next color.
One way I've postulated is to combine both strategies for each percentage, but that would mean I'd have to have 25 if statements nested within each of the 5 if statements I already have for each 1% percentile representation of the data. Is there a better, more efficient way of doing it?
I'm aware that I could limit the number of shades of each colour to a smaller number - but I would like to see if there is any other way to do it besides nesting conditionals.
One way is to use d3.hsl, constructing a color object in terms of 3 pararms: Hue, Saturation and Level.
You'd use something like the switch statement you proposed above to pick a number between 0 to 360 corresponding to the desired hue (green, yellow, orange, red).
Saturation will most likely be a constant, probably between .5 and 1. You'll want to experiment with it and pick a saturation you like.
The level will be a number between 0 and 1, but not too close to 0, because that'll yield black. This number corresponds to the intensity you're representing. The more intense the higher -- hence brighter -- the number. You can use a d3.scale.linear() to convert your data values to be in the 0 to 1 range.
Once you construct the hsl color object, you call .rgb() on it, and that's what you set to be the fill attr of your svg shape.

Categories

Resources