Temperatur einfärben mit JavaScript
Als ich die Temperaturen in meiner Wetteranzeige eingefügt hatte, sahen diese etwas langweilig aus. Zuerst hatte ich eh nur die aktuelle Temperatur. Aber nach dem Einbau des kleinen Wetterausblicks kam mir die Idee, dass ich die einzelnen Werte doch je nach Temperatur anders einfärben könnte.
Im ersten Schritt wollte ich dafür nur drei Kategorien schaffen: Werte unter 0°C als ein kaltes blau, Werte über 30°C als ein warmes rot und dazwischen alles in gelb. Aber das wäre doch zu einfach, das müsste doch mit Hilfe von ein wenig JavaScript besser gehen.
Die Idee war nun, dass jeder Wert eine minimal andere Farbe bekommen würde. Da ich aus Erfahrung wohl keine Temperaturen unter 10°C und über 40°C erwarte, wären dies immerhin bereits 50 verschiedene Werte, sodass ich die Dezimalstellen vernachlässigen kann.
Eine Farbe setzt sich auch drei Anteilen zusammen: rot, grün und blau. Jeweils Werte von 0 bis 255. Orange setzt sich so aus 100% Gelb (255 oder xFF), 50% grün (128 oder x80) und gar keinem blau (0, null, nada, niente) zusammen, was man nun in Hexdezimalem #FF8000 darstellen kann oder mittels rgb() in CSS auch dezimal:
color:rgb(255, 128, 0);
Will man einen Farbverlauf von blau für kalt zu rot für warm, so muss man nur den Wert von rot erhöhen, während man den Wert von blau verringert. Dazwischen liegt allerdings lila - und nicht grün, gelb und orange. Hier kommt nun der Grünanteil der Farbe ins Spiel. Bevor rot erhöht werden kann, muss erst einmal grün das Maximum erreichen. Danach darf rot steigen während blau niedriger wird und letztendlich wird auch grün wieder kleiner, bis nur noch rot übrig bleibt.
Von Wetterberichten sind wir gewohnt, dass sehr kalte Temperaturen, aber auch sehr heiße Temperaturen, vom blau bzw. rot sogar etwa ins Lila gehen. Auch das habe ich in der Funktion berücksichtigt, sodass ich nicht bei klarem blau beginne und kräftigem rot ende. Insgesamt sind es so sechs Phasen.
Nach ein wenig Tüftelei hatte ich dann eine Funktion, die mir genau diesen Zweck erfüllte:
function getRGBofTemp(t) {
	if (t< TEMP_MIN) t=TEMP_MIN;
	if (t> TEMP_MAX) t=TEMP_MAX;
	t = Math.round((t-TEMP_MIN)/(TEMP_MAX-TEMP_MIN)*600);
	m = Math.round((t/100-Math.floor((t-1)/100))*600);
	if(t==0) m = 0;
	n = m * 0.425;
	r = g = b = 0;
	if(t<=100) {
		r = Math.round(FF-n) + Math.floor(n/4);
		g = Math.floor(n/4);
		b = FF;	
	} else if(t>100 && t<=200) {
		r = Math.floor(n/4);
		g = Math.round(n) + Math.floor(n/4);
		b = FF;		
	} else if(t>200 && t<=300) {
		r = Math.floor(n/4);
		g = FF;
		b = Math.round(FF-n);		
	} else if(t>300 && t<=400) {
		r = Math.round(n + n/4);
		g = FF;
	}  else if(t>400 && t<=500) {
		r = FF;
		g = Math.round(FF-n);
	}  else {
		r = FF;
		b = Math.round(n);
	}

	if(r>FF) r=FF;
	if(g>FF) g=FF;

	return r + "," + g + "," + b;
}
In einer kleinen Schleife sieht die Testausgabe für alle Werte dann so aus: Nachdem die Funktion nun aus 50 Werten die entsprechenden Farbwerte ermittelt und diese sich nie wieder ändern, könnte man das Ergebnis auch einfach in einem Array ablegen und abrufen - dürfte etwas schneller sein. Aber langweilig! ;-) Zwei von mir definierte Konstanten geben den Temperaturbereich an, sodass einerseits alle Werte unter MIN bzw. über MAX dann jeweils in der gleichen Farbe angezeigt werden, andererseits sich die Farben innerhalb des Bereiches leicht verschieben können, falls einer ein anderes Wärmeempfinden hat und das grün von 10°C als zu kalt betrachtet:
const TEMP_MIN = -13;
const TEMP_MAX = 42;
Die Flexibiltät mit diesen Konstanten spielen zu können rechtfertigt hier wieder die Funktion anstelle eines fixen Arrays.
Fehlt nur noch ein passender Funktionsaufruf, zum Beispiel um die Temperaturanzeige von "23,5°C" im Farbton für 23 darzustellen:
"<div style=\"background-color:rgb(" + getRGBofTemp(23) + ");\">23,5°C</div>"
Oder mittels einer allgemeinen Funktion, wie ich es in der Wetteranzeige gemacht habe:
function setTempColor(c) {
	$(c).style.color = "rgb(" + getRGBofTemp($(c).getElementsByTagName("b")[0].innerHTML) + ")";
}
Dort kommen an mehreren Stellen die Temperaturen mit festgelegten IDs vor:
<span id="t1"><b>23</b>,5°C</span>
Der folgende Aufruf formatiert dann die Schriftfarbe im Farbton anhand des fettgedruckten Wertes innerhalb von <b>
setTempColor("t1");
Todo: In einer nächsten Version werde ich allen eine Klasse zuweisen und per Funktion diese automatisch parsen.
Ebenfalls schön sieht es aus, wenn die Hintergründe hinter der Schrift anhand der Temperatur farblich dargestellt und die Temperaturangabe an sich schwarz zu belassen wird: Dafür reicht ein einfaches Austauschen von color zu background-color (im CSS-Style) oder backgroundColor (in der JS-Funktion).
Das Blau von -3.6°C wirkt als Hintergrund bei einer schwarzen Schrift schon fast zu dunkel. Bei der "hellen" Variante in weiß sind die anderen Werte hingegen noch viel schlimmer: