Prerequisites:
Read one of the following:
Although this lesson is geared towards the canvas, the concepts of color and gradients presented here are widely applicable to many graphics APIs, including, of course, SVG, which we will study later in this course.
By now you know that we can set the fillStyle or strokeStyle property to choose colors for drawing:
ctx.fillStyle = "teal";
ctx.strokeStyle = "maroon";But of course you may be wondering what other colors there are. What about exotic color names like feuillemorte and viridian? And besides names, can we specify colors by numbers?
The canvas adopts the means of specifying colors from CSS Color Module Level 3 (CSS3). CSS is Cascading Style Sheets, a style language devised for web pages. CSS3 defines 16 basic color keywords or color names: black, silver, gray, white; navy, blue, teal, aqua; yellow, olive, lime, green; red, maroon, purple, and fuchsia. These basic color names were available in HTML4 (or even earlier).
Now, don’t just take my word for it, but look at the CSS3 colors specification, section 4.1, basic color keywords.
Besides, you’ll want to know what these colors look like, and I’m not showing any pictures of them when the W3C has done such a excellent job of that in their color specification! So, if you didn’t already, look at it, right now, and then come back.
You’ve been there, right? Good!
Besides these 16 basic color keywords, there are 147 extended color keywords, taken from the SVG specification, which had previously taken them from the X11 colors—the X Window System at one time stored these in a file named “rgb.txt”; newer versions of X11 have gotten rid of the file but still have the color names.
Take a look at these, just to get a sense of the naming style and the variety of colors. You can look either
Look now, then come back!
Are you back? (Don’t say you’re back if you didn’t go away.)
I hope you found 147 rather appealing and cleverly named colors. But were viridian and feuillemort among them?
If our colors don’t have recognized names, then we have to describe them by numbers.
There are several ways to describe colors numerically, called color spaces or color models; we’ll look at the two methods used in CSS3, which are RGB (red, green, blue) and HSL (hue, saturation, lightness).
You’re familiar with this idea, I hope: by mixing light in the primary colors of red, green, and blue, we can obtain any color. In CSS3, each color component is an integer in the range 0 to 255, and colors are described as rgb(RED, GREEN, BLUE); for example, rgb(255, 128, 0) has the full amount of red, about half the full amount of green, and no blue at all. Alternatively, the components can be given as percentages, so rgb(100%, 50%, 0%) is the same color.1
RGB colors can also be specified in hexadecimal (base 16) notation. If you’re not familiar with hexadecimal notation, don’t worry about it: I’m not going to use it in this course, beyond the end of this paragraph; and you’ll get a dose of it in INFO I308 Information Representation. For the record, though, you can use either 6 or 3 hexadecimal digits, and the form of notation is #RRGGBB or #RGB. For example, #ff8000 or #f80 is again the same as rgb(255, 128, 0).
If you’re not very familiar with RGB colors, fire up your favorite drawing or painting program and use its color chooser to sample some colors in the RGB space.2
HSL stands for Hue, Saturation, Lightness, and is a much more intuitive color space than RGB.
Hue is measured in degrees, from 0 to 360. So at 0 degrees, we have red, 60 is yellow, 120 is green, 240 is blue, and as you venture beyond 240 you get increasingly purple and ultimately return to red at 360.
Saturation is the degree to which the hue “flavors” the color. We can think of it as the amount of dye you dissolve in water or some other solvent. With no saturation at all, you have just gray, with no hue at all. Saturation is measured from 0% (all gray) to 100% (all hue).
Lightness is, of course, the brightness (i.e., non-darkness) of the color. Like saturation, it is measured from 0% to 100%. 0% lightness is black, regardless of the hue. 100% lightness is white, regardless of the hue. 50% is “normal” lightness, which makes the hue most apparent.
Pictures make this much clearer than words. Once again, the W3C has done an excellent job of visualizing these concepts, so I am going to refer you to their diagrams in the CSS3 colors specification, section 4.2.4.1: HSL examples. Go there, study the examples, then come back.
Okay, you’re back! (You did go look, didn’t you?)
If hsl(120, 100%, 50%) is green (i.e., just a normal green, completely saturated and at the normal 50% brightness), then compare it with the following colors. How do you interpret these—how would you describe them in words? Try to answer based solely on your understanding of the HSL color model:
hsl(120, 80%, 50%)hsl(120, 25%, 50%)hsl(120, 100%, 75%)hsl(120, 100%, 25%)You might be able to sample some HSL colors, too, in your favorite paint or draw program, but be careful: some of them will offer HSV (Hue, Saturation, Value), which is not the same as HSL. If you use an HSV color chooser and plug the numbers into HSL, you will get some unpleasant surprises.
There are many HSL color pickers on the web; here are a couple, which you can use to check your answers to the color interpretation questions above:
You can search for more.
The colors we’ve used so far have been opaque. Consequently, in Example 03-01, the first rectangle drawn is partly hidden by the second, as though the first rectangle is behind the second.
We will now extend our color models to allow various degrees of transparency, using a parameter alpha (α). You will sometimes hear of “alpha transparency,” but actually α represents the opacity of a color, which is the opposite of transparency.
The α parameter ranges from 0 to 1, with 1 = totally opaque, 0.5 = 50% transparent, and 0 = completely transparent. Of course, α can be also be 0.25, 0.75, or any number between 0 and 1.
The transparency of a color, therefore, is 1 − α.
When we extend RGB with α, we have the RGBA color space:
rgba(0, 0, 255, 1) is opaque blue, the same as rgb(0, 0, 255);rgba(0, 0, 255, 0.5) is semi-transparent blue;rgba(0, 0, 255, 1) is transparent blue.3When we extend HSL with α, we have the HSLA color space:
hsla(240, 100%, 50%, 1) is opaque blue, the same as hsl(240, 100%, 50%);hsla(240, 100%, 50%, 0.5) is semi-transparent blue,hsla(240, 100%, 50%, 1) is transparent blue.Draw overlapping rectangles, with various degrees of transparency.
See the Gallery’s Canvas Studies; select “Rectangles.”
Besides colors, there are two other types of “style” that we may assign to the fillStyle or strokeStyle of the graphics context: gradients and patterns.
A gradient is a gradual transition from one color to another, or more generally through a series of colors. A pattern is a repeated image, usually a small image; it’s often called a texture in 3D graphics. We’ll learn about gradients now, and about patterns in another lesson.
Gradients come in two flavors:
This statement creates a linear gradient along a line from (x1, y1) to (x2, y2):
var g1 = ctx.createLinearGradient(x1, y1, x2, y2);
// Starts at x1, y1; ends at x2, y2A linear gradient is vertical if the y coordinates are different and the x coordinates are the same; it is horizontal if the x coordinates are different and the y coordinates are the same. It is convenient to let both x coordinates be zero in a vertical gradient, and to let both y coordinates be zero in a horizontal gradient.
The next statement creates a radial gradient, from a circle with center (x1, y1) and radius r1, to a circle with center (x2, y2) and radius r2:
var g2 = ctx.createRadialGradient(x1, y1, r1, x2, y2, r2);
// Starts at a circle centered at x1, y1, radius r1;
// ends at a circled centered at x2, y2, radius r2.The HTML5 specification tells how to create radial gradients, but does not explain what they are. The Safari canvas guide explains that a radial gradient defines a “color change along a cone between two circles.”4 However, we should not take this too literally, because a cone is a 3-dimensional figure, and in the canvas we are working in 2 dimensions. Mozilla’s canvas tutorial cautions that “It’s best to try to avoid letting the inside and outside circles overlap because this results in strange effects which are hard to predict.”5 My experience has been that strange effects may result if one of the circles does not lie entirely within the other. Perhaps this is what the Mozilla tutorial means, although it is not what it says.
We have just created two gradients, with geometry specified by createLinearGradient and createRadialGradient.6
But, we also want to specify some colors. We do this by adding color stops. A color stop is a “point” along the gradient where it is fixed at a particular color. The “points” range from 0 to 1 (0 is the beginning of the gradient, 1 is the end). Between the color stops, the colors are interpolated.
Here we add three color stops:
g1.addColorStop(0.0, "black");
g1.addColorStop(0.5, "green");
g1.addColorStop(1.0, "red");
ctx.fillStyle = g1; // use gradient as fill styleSome rectangles with linear gradients.
Some rectangles with radial gradients.
See the Gallery’s Canvas Studies; select “Radial gradients.”
At least approximately the same: 50% of 255 is 127.5, and our color components are integers, so it must be rounded up or down.↩︎
In case you don’t have a favorite, I take this opportunity to recommend GIMP and Inkscape.↩︎
Transparent blue is really just transparent, so it looks the same as transparent green, transparent red, or transparent anything. Even transparent black!↩︎
Apple Computer, Safari HTML5 Canvas Guide, “Gradients and Patterns”, retrieved 2012 Aug 07.↩︎
Mozilla Developer Network, Canvas tutorial, “Applying styles and colors”, retrieved 2012 Aug 07.↩︎
Gradient coordinates refer to the coordinate system in which the path is drawn. ↩︎