2012-08-07 12 views
23

Eventuali duplicati:
Color coding based on numberGenerare colori tra rosso e verde per una gamma di ingresso

che voglio per un utente sia in grado di scegliere tra una gamma 1-100, dove man mano che i numeri diventano inferiori a 50, il colore dell'area diventa verde più scuro e man mano che il colore diventa più vicino a 100, il colore diventa più rosso.

Sto provando a fare in modo che, come l'intervallo in più verso il centro, il colore dovrebbe essere vicino al bianco (dove 50 = bianco pieno).

ho cercato la risposta da qui: Generate colors between red and green for a power meter? inutilmente .... 50 finisce per essere un verde confusa ...

ho il seguente codice HTML:

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

E il seguente 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/

Ho provato molte combinazioni diverse di r, g, b ma non riesco davvero a farlo bene.

+2

@ Jean-FrançoisCorbett cosa diavolo vuoi dire? – Neal

risposta

12

mi si avvicinò. con questa risposta con un po 'di aiuto da here, che utilizza un Interpolate funzione in cui posso impostare facilmente i colori di inizio e fine.

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/

+0

+1 Esattamente quello che stavo cercando. Ottima soluzione. – Danscho

4

In un modo ondulato mano molto, penso che lo farei in questo modo:

Fai la gamma 1-50 hanno il massimo verde (FF), ed un valore in scala sia rosso e blu che vanno da 00 per il rosso e blu a 1, tutto il tragitto fino a FF per il rosso e blu a 50.

(valori esemplificativi: 1 -> 00FF00, 25 -> 7FFF7F, 50 -> FFFFFF)

Poi da 51 -100, mantenere rosso a FF, mentre ridimensionamento blu e verde in modo che l'approccio blu e verde 0 come si raggiunge 100.

(valori campione: 51 -> FFFFFF, 75 -> FF7F7F, 100 -> FF0000)

Questo è garantito per darvi verde brillante a 0, bianco a 50, e il rosso a 100.

Le aree in mezzo potrebbe non essere esattamente perfetto, semplicemente perché l'occhio interpreta diversamente intensità di colore differenti (siamo migliori in alcuni colori rispetto ad altri), ma dovrebbe avvicinarti abbastanza.

ho modificato il codice nel tuo piano rispetto a quanto segue e fa quello che ho descritto:

$(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); 
     if (val <= 50) 
     { 
      r = Math.floor((255 * (val/50))), 
      g = 255, 
      b = Math.floor((255 * (val/50))); 
     } 
     else 
     { 
      r = 255, 
      g = Math.floor((100 - val)/50 * 255), 
      b = Math.floor((100 - val)/50 * 255); 
     } 
     span.css({ 
      backgroundColor: "rgb(" + r + "," + g + "," + b + ")" 
     }); 
    } 
}, "input[type='range']"); 
+0

Hai un esempio che puoi mostrarmi? :-) – Neal

+0

@Neal Aggiunto un esempio di codice da inserire nel tuo violino. (Ho cambiato i riferimenti var a global per questo esempio, ma è abbastanza semplice.) – Beska

+0

La tua soluzione funziona :-) Ho aggiunto il mio che ho trovato che mi permette di essere flessibile con i miei colori :-) – Neal

39

che stai ricevendo il verde confusa a causa del modo in cui si sta creando il gradiente nello spazio RBG. Per ottenere un gradiente "più pulito", è possibile utilizzare il modello HSV come menzionato in the answer of the question you linked to.

RGB gradiente (in alto) vs HSV (in basso) top gradient uses RGB, bottom uses HSV

Scalando il valore H (tonalità) compreso tra 0 (rosso) e 120 (verde) si otterrà un bel passaggio pulito .Tuttavia, nel punto medio (60) ti ritroverai con un giallo brillante invece del bianco desiderato. Puoi risolvere questo problema modificando il valore S (saturazione) - a saturazione 0, finirai con il bianco (1 ti dà saturazione completa del colore

Ecco un esempio grezzo che ridimensiona la saturazione da 1 a 0 e torna a 1 come il valore di ingresso va da 0 a 50 a 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 

ps la conversione tra i modelli di colore è facile utilizzando jquery-colors, anche se non è troppo difficile da rotolare il proprio