I have a collection of handy color spectrum classes in my personal library that are useful for creating a variety of color-picker components and what not. I thought I would share a few of them with you, as well as discuss the math that is involved in drawing a color spectrum.
Before diving in, I want to clarify how individual RGB channels are merged into one color value to ensure that everyone can follow along. Since each R, G, and B value is commonly represented by a value of ’0′ to ’255′, but when combined make up a single 24-bit color value, you need to understand a little bit about bitwise operations to understand how and why this is the case. In binary, you need 8 bits to represent a value that is up to 255, so ’00000000′ to ’11111111′. That means to represent three of these 8-bit numbers, you need to combine them into one big value of 16.7 million colors. Reading from right to left in binary, the first eight digits are blue, the second set are green, and the third set are red, making up a range of black ’000000000000000000000000′ to white ’111111111111111111111111′.
Now, a bitwise rotation will move a set of digits over to the left or right. So 255 (which is ’000000000000000011111111′) rotated left by 8 becomes ’000000001111111100000000′. So in practice:
- nRed = nR << 16;
- nGreen = nG << 8;
- nBlue = nB;
You may be familiar with the use of sine waves for animation-related tasks, but did you know that they are also the key to drawing a color spectrum? A full cycle of ’0′ to ’2Pi’ with some additional math for offsetting the wave position for each color channel will gracefully rotate through the various color values of the visible spectrum. Once you have calculated each of the individual RGB channels, you can OR the values together to form a single color value.
- nR = Math.cos(nRadians) * 127 + 128 << 16;
- nG = Math.cos(nRadians + 2 * Math.PI / 3) * 127 + 128 << 8;
- nB = Math.cos(nRadians + 4 * Math.PI / 3) * 127 + 128;
- nColor = nR | nG | nB;
In the case of a horizontal color spectrum, you can calculate the angle for the RGB values by using the percentage of the width you are drawing and then converting the degree to radians.
- nColorPercent = i / nWidth;
- nRadians = (-360 * nColorPercent) * (Math.PI / 180);
Now that you have the necessary color information, you are ready to use the Flash drawing API to draw the data to the display. In the case of my ‘ColorBar’ class, I simulate the color bar seen in the Photoshop color palette (with the horizontal color spectrum and a vertical fade from white to black).
- objMatrixW = new Matrix();
- objMatrixW.createGradientBox(1, nHalfHeight, Math.PI * 0.5, 0, 0);
- objMatrixB = new Matrix();
- objMatrixB.createGradientBox(1, nHalfHeight, Math.PI * 0.5, 0, nHalfHeight);
- graphics.lineStyle(1, 0, 1, false, LineScaleMode.NONE, CapsStyle.NONE);
- graphics.lineGradientStyle(GradientType.LINEAR, [0xFFFFFF, nColor], [100, 100], [0, 255], objMatrixW);
- graphics.moveTo(i, 0);
- graphics.lineTo(i, nHalfHeight);
- graphics.lineGradientStyle(GradientType.LINEAR, [nColor, 0], [100, 100], [0, 255], objMatrixB);
- graphics.moveTo(i, nHalfHeight);
- graphics.lineTo(i, nHeight);
Here is the result:
Another nice way to present this data is in circular form (also known as a color wheel). We use the same method for calculating the RGB channels as before; however this time we can loop from ’0′ to ’360′ degrees and simply convert the degree to radians.
- nRadians = i * (Math.PI / 180);
To render the circle itself, we use the angle of the color to plot the coordinate we are drawing the line to from the center of the circle.
- nX = nRadius * Math.cos(nRadians);
- nY = nRadius * Math.sin(nRadians);
Now, like last time, we just use the Flash drawing API to draw the data. Note that the critical piece here is the matrix which is used to transform the gradient for the line being drawn; it must be rotated to match the angle of the line itself.
- objMatrix = new Matrix();
- objMatrix.createGradientBox(nRadius * 2, nRadius * 2, nRadians, -nRadius, -nRadius);
- graphics.lineStyle(iThickness, 0, 1, false, LineScaleMode.NONE, CapsStyle.NONE);
- graphics.lineGradientStyle(GradientType.LINEAR, [0xFFFFFF, nColor], [100, 100], [127, 255], objMatrix);
- graphics.moveTo(0, 0);
- graphics.lineTo(nX, nY);
And the result:
The math I have just demonstrated is extremely useful in working with color and can be used for much more than just simple little color-picker components. Below is a zip file that contains all the source for the color spectrums shown above.
I hope you will find this both useful and inspiring.22 comments