Set background color based on outdoor temperature
Asked Answered
P

4

18

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.

Temperature color schema

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

Presnell answered 6/5, 2013 at 13:20 Comment(16)
why don't you just add the appropriate css class based on some conditional logic?Ablepsia
you mean to add a class like .temperature-minus-20 that should display a defined background-color ? I know this is a working way, but I have to define all those classes in advance in CSS, and I would prefer to not manage it in a "step-based" way, if it's possible !Presnell
not exactly, but just get a general range of values that could be represented.Ablepsia
How would you make it without step-based classes ? I guess that I do not exactly see what do you suggestPresnell
@George -- how is this "too localized"? Is this not a legitimate question that could help others?Rid
+1, I can't understand how or why this question could become "too localised" ?!Presnell
@LittleBobbyTables As written, it's not a good question for Stack Overflow (besides the normal title, punctuation, and grammatical issues) "I need someone to write an algorithm to define a temperature by its color". Great. No research effort; overly broad; maybe even 'shopping' for a solution. I fat fingered it when I closed it as "Too Localized", it should have been closed as "Not a Real Question", as the flag stated.Pyrimidine
Sorry about closing it for the wrong reason. As I said, I fat fingered the close reason.Pyrimidine
@GeorgeStocker So sorry, I wasn't born in any english country, should I maybe die for this reason ? If there are grammatical issues, isn't it better to just edit the question ? But more, how can you say "No research effort" or "I need someone to write an algorithm for me" ????? I said I read another thread, and a quite complex Wikipedia article on colors, Do I have to write a thesis about a question I am asking for ? And - as written in the question - I am just asking for some ideas, not for a complete algorithm !!!!!Presnell
@Flo-Schield-Bobby just asking for ideas isn't valid. please read the faq: stackoverflow.com/faq#dontaskAblepsia
@DanielA.White, I read it: "If your motivation for asking the question is “I would like to participate in a discussion about ______”, then you should not be asking here. However, if your motivation is “I would like others to explain ______ to me”, then you are probably OK." I guess this question goes to the 2nd point, no ? If you don't like this question, why don't you just ignore it ? It has been upvoted, so I guess that some people are interested ?Presnell
I find the question easy to understand and valid. If I had enough time, I'd create a solution. But have a look at this: tannerhelland.com/4435/convert-temperature-rgb-algorithm-codeX
This is an answer-comment that I expected people to write. Thanks, @Atle, I'll take a serious look and publish the answer if I can work with this !Presnell
It's an interesting problem. I looked a bit closer at the link, and see that the problem there is slightly different. The algorithm is based on Kelvin temperatures and a logarithmic scale. Also it transfers from warm to cold through white, while you need some darker shade. But it should be possible to adapt the functions. Or you could google for temperature to rgb conversion. Also, for any real application there is no shame in precalculated tables. It's faster and more efficient, and a common way to do things like this. :)X
Yeah sure, I know that, but I was wondering if it was possible to define a algorithm, for the sake of science :)Presnell
Don't you guys think we can now reopen this question? Maybe it is misphrased, but stays totally valid and interesting. It seems that @GeorgeStocker simply fat fingered the close button, not just the reason why it is now, closed. Remember that most of us, contributors, aren't native english speakers, and we are probably the right people to understand/correct this.Mawson
E
1

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!

Epochmaking answered 9/5, 2013 at 3:12 Comment(1)
The first option looks really great ! But I'm not sure to understand all the points, I'll concentrate a bit later on this. I am currently using the 3rd option which works in a cleaner way that I expected to do. I will take some time to think about the first, however ! Thanks !Presnell
S
8

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/

Stpeter answered 9/5, 2013 at 18:22 Comment(3)
The project is webkit-based but I would like to develop a library that I could use on many browsers, so I think I would prefer to conversion to RGB. Thanks a lot anyway, I'll try integrate it in my current solution and let you know my feedbacks !Presnell
I like where you're going with this, but how would you get the h, s and l values from your hue calculation? Also, is t in celcius?Diverse
I don't know what the OP's t is, but it looks like it could well be Celcius. The point of my answer is simply to map the range [-30 .. +30] to [270 .. 30]. S and L both look to be around the 0.7 mark.Stpeter
M
3

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();
};
Makhachkala answered 9/5, 2013 at 19:8 Comment(2)
Yeah thanks, sounds very interesting, could you just explain a bit what are those constants that you use ? Is it based on the gradient values or any algorithm ?Presnell
Good point. The constant .35 in the power function is totally arbitrary. That compressed the middle of the gradient "nicely." The h0 and h1 are hue values (0-360) that map to a purple and orange-red (roughly) as in the original question. The 75 and 90 are arbitrary saturation and value values for the color. In other words, the constants are based only on what looked nice, not a physically-based algorithm of any sort.Makhachkala
W
2

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.

Wiseacre answered 9/5, 2013 at 18:15 Comment(4)
blending the RGB values of colours that only differ in hue tends to produce "muddy" looking mixes.Stpeter
You're right, both of you two, I discovered these points but didn't have the good feeling to edit the question until it was reopened ! But thanks ! I currently use a gradient array and it works well, but you have to choose your colors steps to avoid that "muddy" problem. And @Alnitak, as I am working in a LAB color space, I can avoid that blending problem - at least I guess.Presnell
If the intervalls aren't too large, then RGB seems OK. I prepared an example here. LAB is probably the best, but less performant...Wiseacre
That's what I've got with Lab. I didn't see this performance trick, even if I don't really care for this project, it could be nice to test it at the end. Thanks again !Presnell
E
1

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!

Epochmaking answered 9/5, 2013 at 3:12 Comment(1)
The first option looks really great ! But I'm not sure to understand all the points, I'll concentrate a bit later on this. I am currently using the 3rd option which works in a cleaner way that I expected to do. I will take some time to think about the first, however ! Thanks !Presnell

© 2022 - 2024 — McMap. All rights reserved.