Mr Speaker

Nicer random colours, with HSL

As many of you may know from my complaining, I've currently embarked on a new writing mission: a CoffeeScript book for SitePoint. The example project that runs throughout is an HTML5 game using Canvas. While I was trying to create a random colour palette - for instructional purposes - I fell over this "trick" of using HSL rather than RGB to pick more pleasant-ish colours.

Choosing nice looking random colors with a very small amount of code can be tough. Usually you end up with a function that picks a number between 0 and 255 and then concats 3 runs together as a string to create a valid RGB number (something like rgb(chooseCol() + "," + chooseCol() + "," + chooseCol());

The problem is choosing from the whole spectrum of available colours and shades is pretty ugly. The solution for the demo above is to use HSL (Hue/Saturation/Lightness) colours. HSL is an alternative to the RGB and hex (#00000-style) color definitions. In HSL, the first value represents the hue in a range: 0 (and 360) is red, 120 is green, and 240 is blue. Other numbers are shades in between them.

The second parameter is the saturation, and the last is the lightness. These parameters are defined as percentages.

To get our array of colors with HSL we just choose a random shade between 0 and 360, turn the saturation and lightness down a bit, and voila - nice random colors. Because the saturation and lightness is the same, the colours work nicely together.

var ctx = document.getElementById("hsling").getContext("2d"),
    noise = function(){
      for(var y = 0; y < 6; y++) {
        for(var x = 0; x < 30; x++) {
          var color = ~~(Math.random() * 360);
          ctx.fillStyle = "hsl(" + color + ", 60%, 60%)";
          ctx.fillRect(x * 15, y * 15, 14, 14);

setInterval(noise, 100);

Simple, but nicer than my usual RGB technique. Pretty much all of the modern browsers (including IE9) support HSL colours in CSS too - so the trick can be used everywhere random colours are needed. Which is everywhere!

UPDATE! Oops - got yelled at for not actually supplying a CoffeeScript version! But I mean, it's pretty much exactly the same... here's the guts of it, off the top of my head!

noise = ->
  for y in [0..5]
    for x in [0..29]
      color = ~~(Math.random() * 360)
      ctx.fillStyle = "hsl(#{color}, 60%, 60%)"
      ctx.fillRect x * 15, y * 15, 14, 14

Captcha! Please type 'radical' here: *
How did you find this thingo? *