Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate colors between red and green for an input range [duplicate]

Possible Duplicate:
Color coding based on number

I want for a user to be able to select from a range from 1-100, where as the numbers become less than 50, the color of the area becomes darker green, and as the color becomes closer to 100, the color becomes more red.

I am trying to make it so that as the range in more towards the center, the color should be close to white (where 50 = full white).

I tried the answer from here: Generate colors between red and green for a power meter? to no avail.... 50 ends up being a muddled green...

I have the following html:

<span><span class="value">50</span><input type="range" /></span>​ 

And the following javascript:

$(document).on({     change: function(e) {          var self = this,             span = $(self).parent("span"),             val = parseInt(self.value);         if (val > 100) {             val = 100;         }         else if (val < 0) {             val = 0;         }         $(".value", span).text(val);         var r = Math.floor((255 * val) / 100),             g = Math.floor((255 * (100 - val)) / 100),             b = 0;         span.css({             backgroundColor: "rgb(" + r + "," + g + "," + b + ")"         });     } }, "input[type='range']");​ 

Fiddle: http://jsfiddle.net/maniator/tKrM9/1/

I have tried many different combinations of r,g,b but I really cannot seem to get it right.

like image 508
Naftali Avatar asked Aug 07 '12 15:08

Naftali


2 Answers

You're getting the muddled green because of the way you're creating your gradient in RBG space. To get a "cleaner" gradient, you can use the HSV model as mentioned in the answer of the question you linked to.

RGB gradient (top) vs HSV (bottom)top gradient uses RGB, bottom uses HSV

By scaling the H (hue) value between 0 (red) and 120 (green) you'll get a nice clean transition. However, at the mid point (60) you'll end up with bright yellow instead of your intended white. You can address this by modifying the S (saturation) value -- at 0 saturation, you'll end up with white (1 gives you full colour saturation.

Here's a crude example which scales the saturation from 1 to 0 and back to 1 as the input value goes from 0 to 50 to 100 - http://jsfiddle.net/xgJ2e/2/

var hue = Math.floor((100 - val) * 120 / 100);  // go from green to red var saturation = Math.abs(val - 50)/50;   // fade to white as it approaches 50 

p.s. Converting between colour models is easy using jquery-colors, although it's not too hard to roll your own.

like image 86
Shawn Chin Avatar answered Sep 20 '22 09:09

Shawn Chin


I came up with this answer with some help from here, which uses an Interpolate function in which I can set the start and end colors easily.

function Interpolate(start, end, steps, count) {     var s = start,         e = end,         final = s + (((e - s) / steps) * count);     return Math.floor(final); }  function Color(_r, _g, _b) {     var r, g, b;     var setColors = function(_r, _g, _b) {         r = _r;         g = _g;         b = _b;     };      setColors(_r, _g, _b);     this.getColors = function() {         var colors = {             r: r,             g: g,             b: b         };         return colors;     }; }  $(document).on({     change: function(e) {          var self = this,             span = $(self).parent("span"),             val = parseInt(self.value),             red = new Color(232, 9, 26),             white = new Color(255, 255, 255),             green = new Color(6, 170, 60),             start = green,             end = white;          $(".value", span).text(val);          if (val > 50) {             start = white,                 end = red;             val = val % 51;         }         var startColors = start.getColors(),             endColors = end.getColors();         var r = Interpolate(startColors.r, endColors.r, 50, val);         var g = Interpolate(startColors.g, endColors.g, 50, val);         var b = Interpolate(startColors.b, endColors.b, 50, val);          span.css({             backgroundColor: "rgb(" + r + "," + g + "," + b + ")"         });     } }, "input[type='range']");​ 

Fiddle: http://jsfiddle.net/maniator/tKrM9/53/

like image 22
Naftali Avatar answered Sep 18 '22 09:09

Naftali