Tuesday, 28 April 2009

Setting Colours with JavaScript

Something I thought would be easy turns out to have lots of different answers, none of which are particularly convenient: how do you compute a colour value in JavaScript, and then update some element on the page to use that colour?

Most solutions I've seen involve some kind of hard-coded hexadecimal conversion table, which is more than a little clunky. So here's another approach. Here, the value used to compute the colours is a ratio, with a value from 0.0 and up (normally in the 0.0 to 2.0 region, but theoretically unbounded at the top). I want to use red to indicate a ratio of 0.0, green for ratios of 2.0 or more, and a smooth range of colours in between.

So, onto th JavaScript (yes, I have the ratio conveniently in a hash table):

var ratio = parseFloat(data["ratio"]);
var red = 255 - (ratio * 255); // calculate
var green = ratio * 128;
if (red < 0) red = 0; // clamp
if (green > 255) green = 255;
var colour = ((red << 16) | (green << 8) | 0).toString(16);
while (colour.length < 6) colour = '0' + colour;
document.getElementById("ratio").style.color = '#' + colour;

The magic is in knowing that colours are typically represented as a red-green-blue triplet, with a byte in each channel (range 0-255). Blue doesn't feature in our range, so it's always zero. So, assembling the necessary triplet is just a matter of getting the clamped value for the right fields, and then OR-ing them together in a bitwise fashion after putting the red and green values in the correct place with the appropriate shifting. Then the toString(16) returns that integer in base-16, which happens to be what makes sense in CSS land. Finally, pad the string out with zeroes on the left (the string needs to be six characters long, then slap on the '#' to have it make sense in CSS land and you're done.