12/2011: Charlie Loyd has written a nice analysis of the techniques presented in this article, and makes
a good case for sine-generated rainbows as an aesthetic improvement over the more common HSB-space rainbows (which have brightness/saturation spokes).

1/2011: Since I wrote this tutorial, CSS3 has introduced the hsla() color specifications, which makes the kinds of tricks explained in
this article much easier on browsers that support CSS3. Since my intent was to teach some simple color theory and applied mathematics, I suggest
you pretend this feature doesn't exist as you read this article. Then, afterwards, use it willy nilly!

This is a tutorial on how to produce sequences of discrete colors, for use in fonts, graphics or tables, such as
in the color strips shown here, or the title of this article.

Obviously you can make a webpage look incredibly annoying if you
overuse this technique (and by overuse, I mean use at all), but you may have fun learning to do it, and you will improve your javascript skills, and your
understanding of how colors work.

I am going to use javacsript for my code examples, but you can use the same
basic techniques in any language, and indeed I originally developed these tricks in C, but I now use the same old
tricks in C++, Perl, Processing, Java, Flash Actionscript and other languages.

To get the most out of this tutorial, you will need to know a little Javascript, and a little HTML. However, you won't
need to know a whole lot. I mean c'mon. I even explain how hexadecimal works in this document, and why
'#FF0000' comes out red, and so on...

Converting R,G,B values to HTML hex notation

On computer monitors, you get different colors by combining red, green and blue. The red, green and blue levels are called 'color components'.

To generate rainbow-like sequences of colors, I am going to be manipulating the individual RGB components of each subsequent color.
So the first thing I need is a utility function to convert individual red, green and blue values to an HTML hex color specification, which
looks something like this:

#AABBCC

This represents an RGB color with 8-bits per component. In an 8-bit color system, the values of the color components, R, G, and B can
go from 0-255. But the HTML color specification uses hexadecimal notation for each of the components, so that they each occupy two digits.

In hexadecimal, each color component (red, green, and blue) occupies two digits, like so:
#RRGGBB. So our color has the following hex values:

Component

Value (in hex)

Red

AA

Green

BB

Blue

CC

Hexadecimal numbers are base 16 numbers. You can use the following table to convert two digit hex numbers to their
decimal equivalents.

Hexadecimal

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

Decimal

0

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

If you don't have a calculator handy that does hexadecimal -> decimal conversion, it's not too hard to do it yourself.
Just take the first digit, convert it to decimal (using the above table, which is easily memorized, especially if you're not busy friday), multiply it by 16, and
then add the decimal equivalent of the second digit. For example, the number AB corresponds to 10*16 + 11, or 171.

Using this formula, you will see that the color #AABBCC corresponds to the following values:

Component

Value (in hex)

Value (in decimal)

Red

AA

170

Green

BB

187

Blue

CC

204

What I need for this tutorial is a function that does the reverse - converts 170,187,204 back to #AABBCC.
I would use it like this:

output = RGB2Color(170,187,204);

And know that the string '#AABBCC' is in the output value, ready to be output as HTML, using the document.write() command.

This function relies on the binary arithmetic operators >> and &, which treat the numbers as binary, which is closely
related to hexdecimal. Every 4 bits (or binary digits) in a binary number corresponds to a single hex digit, 0-F.
So this function takes the leftmost 4 bits of the number (given by n >> 4, which shifts the number right by 4 bits) and converts it to hex, and then takes
the rightmost 4 bits of the number (given by n & 0x0F, which masks off the rightmost 4 bits) and converts it to hex.

I should point out that decimal -> hex conversion (and number formatting in general) is much easier in languages that provide a 'printf' function - something sorely missing from Javascript.

In Perl, you can do this same conversion in one line, like so:

output = sprintf '#%02x%02x%02x', $r, $g, $b;

If you can live without an old-style CSS color specification, you can also produce colors more simply without byte2Hex, like so:

Sine wave cycles

The basic tool I am going to use to make color cycles is the sine wave. There is a function in Javascript, Math.sin() which
will produce a smoothly undulating value that goes from 0 to 1 to 0 to -1 and back to 0. Here are some samples:

Sine waves are really useful in real life, contrary to what you might have inadvertantly learned in trig class, and they are especially useful for all kinds of things relating to graphics and music.

To get this pattern, I have input into the Math.sin() function a value which is steadily increasing. You can
produce a series of sine wave values using a loop, like so:

You may have noticed that the sine wave pattern starts to repeat right about when frequency*i is equal to 6.2. The precise value where it repeats is actually
2π (2 times PI) or 6.28318, which happens to correspond to the circumfrence of a circle with a radius of 1. As you may already know,
sine waves are closely related to circles. The halfway point in the sine wave is π exactly, or 3.14159...

At this time I would like to apologize for how crappy the π (PI) character looks in the san-serif font used in 80% of the computers out there. If I were
using lovely Times Roman, the π character would be far more recognizeable. Sadly, I'm not, because for just about everything else
I find the San Serif font more readable. But I digress...

There is a relationship between these π units which are used with the Math.sin() function (called radians) and the more familiar degrees which go from 0-360
(degrees are an old Babylonian unit -- the Babylonians really liked numbers like 60 and 360 because all kinds of numbers go evenly into them. Also, the Babylonians hadn't
invented pie yet...)

Degrees

Radians

0

0

90

π/2

180

π

270

3*π/2

360

2*π

You can produce a value for π in Javascript by saying:

document.write(Math.PI);

Like so:

I personally have π memorized up to 8 digits. Kind of a waste of gray matter, really.

Speaking of gray matter...

Using sine waves to make shades of gray

I can use the return value of Math.sin() to make fluctuating color values. However, I need to do
a little conversion. As shown above, the return value of Math.sin() goes from -1 to 1. The color components I use to
make RGB colors go from 0 to 255. So I need to translate a number from the range (-1 --> 1) into (0 --> 255).

This isn't too hard because we know that we want the sine value to start at some center value, and then
go up and down by some amount. Since the sine wave goes up to 1, and down to -1, it is already normalized
(meaning that it's maximum value is 1, a very useful number). We can just multiply it by some other number, and it will go up to that number, and down to the negative version of that number.

For our color values, it will work well if we use 255/2 for our center value, and have the sine value go up and down with an amplitude of 255/2 (which
will take us to 255 and down to 0.

color_component = Math.sin(frequency*i)*255/2 + 255/2;

I usually express this, using integers, as:

color_component = Math.sin(frequency*i)*128 + 127;

...which isn't exactly the same, but close enough.

More generally, when we want to use a sine wave to oscillate something, we will use the formula

value = Math.sin(frequency*increment)*amplitude + center;

frequency is a constant that controls how fast the wave oscillatesincrement is a variable that counts up, typically provided by a loopamplitude controls how high (and low) the wave goescenter controls the center position of the wave.

Now I can modify my original sine wave loop, and produce a series of test colors.

Inside the document.write I am producing a color by calling RGB2Color(v,v,v). Since I pass
the same value in 3 times, for red, green, and blue, I will get a gray color. In gray colors, red,
green, and blue have the same value. To view the color, I print out a block character, using the
unicode value &#9608;.

And here's what the code produces -- a kind of color sine wave:

For fun, I can try using a series of different values for frequency. This is what I'll get if I add an
additional outer loop that changes the value of frequency.

Using out-of-phase sine waves to make rainbows

Now, as I mentioned, the reason the above gradient looks gray is beacuse I am using the same value
for red, green, and blue. One way we can try to get colors is to add a constant to the value of v
that we are using for the green and blue parameters. So instead of saying:

RGB2Color(v,v,v)

I might say:

RGB2Color(v,v+30,v+60)

This produces the following color sequence:

This is interesting, but it is not quite what I want. A better technique is to generate 3 out-of-phase
sine waves, by doing something like this:

As you can see I am using the values 2 and 4 to change the alignment (or phase) of the green and blue sine waves. I chose
2 and 4 because they nearly divide the range of the sine wave (2π or 6.2) into three equal parts, which puts each sine
wave approximately 1/3rd of a cycle, or 120°, out of phase, like so:

red (phase = 0)
green (phase = 2)
blue (phase = 4)
RGB

If I wanted exactly 120° I can use 2*Math.PI/3 in place of 2, and 4*Math.PI/3 in place of 4, which produces
this nearly identical (but perfect) color cycle:

However, the results are so close, that I think 2 and 4 are fine substitutes. It is said that ancient Egyptians thought that π was equal to three.
And in this tutorial, we're gonna code like an Egyptian.

More about the hue cycle

This basic phenomenon - that three 120° out-of-phase sine waves produces a rainbow effect is something I've known
about for a long time - since the mid 1980s actually. I originally discovered it just by playing around with using sine waves to make color (a frequent activity which took the place of having a life). Once I learned this trick, I started using it whenever I wanted an assortment of bright colors. For example, the dots
in my Whitney Music Box are colored using this system.

Later, when I learned more about color theory, I found out that what I'm doing is basically causing the hue of the color
to travel around the circle of a color wheel. If you plot the path that I'm making on the hue-saturation
circle commonly seen in color pickers, you'll find it doesn't produce a perfect circle, but more of a trefoil pattern, like so:

Note: I used the Processing language to produce this illustration. Making it in Javascript would be a bit of a
chore. If you like graphics programming in Javascript, you'll love it in Processing.js, and you will enjoy my Processing blog (and unfinished book): The Joy of Processing.

Even though it doesn't make a perfect hue circle, the sine-wave trefoil makes a pretty color gradient, and it's pretty easy to
get a rainbow effect in just a few lines of code. I actually prefer it to the "correct" HSB / HSL hue cycle, because it has more consistent brightness. It minimizes the spokes at yellow, cyan and magenta, which you can see in the picture.

Now, I'll talk about how to modify the function to produce a greater assortment of colors, and different shades, such as pastels.

Generalizing it

In the next few sections, I'm going to use a general purpose function for drawing these color gradients.
It allows me to specify separate parameters for frequency and phase for each color component. Here's the code:

Making pastels

The basic trick to getting pastels is to change the gamut of the color components to use lighter colored values for
the color components. So, when we convert the sine values, instead of convering to the full range (0 --> 255), we convert
to something like (205 - 255). We change the last two parameters (center and width) as follows. Before:

In the changed code, the 230 is the center of the sine wave, and the 25 is the maximum deviation from this
center value. So the sine wave starts at 230, goes up to (230+25) and goes down to (230-25). In other
words, it has a range of (205-255).

And this makes a pastel strip:

I can get darker pastels by using a wider range (center=200, width=55), like so:

Get more stripes by increasing the frequency

When you change the value of frequency, you can get the colors to change more quickly, or more slowly. Up to now,
I've mostly been using an frequency value of .3, but here are some other values:

Experimenting with phase

For the basic rainbow effect, I separated the phases of each sine wave by 120°. What happens if I
put the phases closer together? Let's find out:

Get more variety by using separate frequencies for each component

Another trick I've used which produces greater color variety is to put each color component on a different
frequency. Here's the code:

If I separate out the individual channels, you can see what is going on:

red (freq = .1)
green (freq = .2)
blue (freq = .3)
RGB

Using three different frequencies may produce colors with a low saturation value, such as the black seen in the example above, or grays or whites.
This happens when the three sine waves cross the same value simultaneously.

Getting cycles to repeat

Let's say you want the color cycle to repeat every 6 steps. How do you do it? The way I accomplish
this is by using a frequency value which corresponds to 1/6th of 2π. Remember that the sine wave repeats
every 2π, so this will make the colors repeat every 6 increments. Here's the code...

Getting cycles to not repeat

If you don't want the colors to repeat exactly, then use frequency values which don't go evenly into 2π.
It turns out that the number 2.4 works very well for this. 2.4 in radians, is very close to the golden angle (137.51°), which
is the angle that many plants grow new shoots to maximize the sunlight received by leaves. Here I'm using essentially the same technique -
I am maximizing the distance between color repeats (which would be like overlapping leaves around a stem). 2.4 is a good frequency to use if you're selecting colors for a pie chart or graph, and you're not sure how many data values you're going to need to plot.
Here's the code.

If you combine this with the trick of using separate freqencies for each color, and insure that none of the
individual frequencies are multiples of each other, you can get even more variety.
Here I'm using frequency of 1.666, 2.666, and 4.666.