Creating Rectangles, Fills, Gradients, and Patterns - HTML5 and the Canvas - HTML5, 20 Lessons to Successful Web Development (2015)

HTML5, 20 Lessons to Successful Web Development (2015)

PART II HTML5 and the Canvas

LESSON 10 Creating Rectangles, Fills, Gradients, and Patterns

Images

To view the accompanying video for this lesson, please visit mhprofessional.com/nixonhtml5/.

Now that you’ve seen how to use JavaScript to access the HTML5 canvas, let’s look at all the different functions available for creating different effects, including drawing lines, rectangles, and circles; changing colors; using pattern and gradient fills; writing text; changing font face; using lines, paths and curves; applying images to a canvas; adding shadows; direct pixel manipulation; compositing and transparency; transformations and translations, and more.

Drawing Rectangles

Other than drawing lines (which we’ll get to later, since they are handled using paths), rectangles are probably the simplest type of object you can draw on an HTML5 canvas, as you’ve already seen with the fillRect() function used in a couple of examples.

You can also fill a rectangle with a color other than black, and you can create unfilled (or clear) rectangles with different border widths, line styles, and corners.

Images

Remember that JavaScript functions are also often referred to as methods, but as the terms are interchangeable, I have selected to use only the word function.

The fillRect() Function

We have already explored the fillRect() function; it takes four arguments representing the vertical and horizontal offsets of the top left-hand corner of a rectangle from the top-left corner of the canvas, followed by the rectangle’s width and height, all of which are in units of pixels, or one screen dot.

The syntax of the function is as follows, which creates a filled rectangle 50 pixels wide and 70 pixels high, at an offset of 20 pixels in from the left edge of the canvas (410 by 170 pixels), and 30 pixels down from its top:

Images

This example shows all the bits and pieces needed to set up everything ready to make the call to fillRect(), but for simplicity in the rest of this lesson, I will show only the relevant calls required for the function or functions being explained, like this:

context.fillRect(20, 30, 50, 70)

Images

If you are trying out these examples, you must ensure that you have first created a suitable canvas using the <canvas> and </canvas> tags and specified a suitable width and height for it (with enough room to display whatever is written to the canvas), have entered the O() and S() functions within any preceding pair of <script> and </script> tags (including the current pair), and have created a context for accessing the canvas called context.

The default color of a filled rectangle is black, but you will learn how to change this in the next section, or even how to use a gradient or a pattern to fill it later in this lesson.

The fillStyle Property

Using the fillstyle property, you can set the type of fill color to use, using either short (three-digit) or long (six-digit) hexadecimal colors. For example, to choose red you can pass the values #F00 or #FF0000, like this:

context.fillStyle = ′#F00′

You may also use any of the HTML color names (listed in Lesson 4) such as red, steelblue, and so on, like this:

context.fillStyle = ′red′

Once selected, the color will apply to all fill operations until it is changed. For example, the following pair of lines will create a red rectangle, rather than a (default) black one:

Images

For more information on using colors, please refer to Lesson 4.

The clearRect() Function

If you want to draw a clear rectangle, in which all the RGBA (Red, Green, Blue, and Alpha transparency) values of a pixel are set to zero, you can use the clearRect() function, as follows:

context.clearRect(20, 30, 50, 70)

This function uses the same arguments as fillRect(), namely the horizontal and vertical offset of the top left-hand corner of the rectangle from the top-left corner of the canvas, followed by the width and height of the rectangle to clear.

The cleared area will be stripped of all color, leaving only any underlying background color that may have been applied to the <canvas> tag (and which therefore is not part of the canvas, but is actually underneath it).

The strokeRect() Function

With the strokeRect() function, you can create a rectangle that uses the current strokeStyle, lineWidth, lineJoin, and miterLimit properties to draw the border lines and corners (as detailed in the “Drawing Lines” section in Lesson 12), and is used like this:

context.strokeRect(20, 30, 50, 70)

The function takes the same arguments as fillRect(), namely the horizontal and vertical offset of the top left-hand corner of the rectangle from the top-left corner of the canvas, followed by the width and height of the rectangle to draw.

It is possible to apply these effects on their own or in combination with others, so the following code (in which I have lined up the columns of arguments for ease of comparison) is valid and results in Figure 10-1, in which a red outer square created using fillRect() has a clear one drawn over it using clearRect() (because it’s clear all you see is a thick-lined outer rectangle—the inner area of which has been cleared). Within the clear square is another lined rectangle which was created using the strokeRect() function:

Images

Images

FIGURE 10-1 The three types of rectangle drawn inside each other in red

Images

I have covered rectangles before lines because they are simpler to draw. As you will see in Lesson 12, lines must be drawn by creating paths of locations that you connect up. Therefore, the properties that are associated with lines and paths are explained in that section, rather than here.

Creating Gradients

You saw how to create a simple, filled rectangle in the previous section, but it’s also easy to apply a variety of different types of gradient to both the fillRect() function, as you’ve already seen, and the fill() function, which is introduced later on.

The createLinearGradient() Function

The simplest type of gradient available with the HTML5 canvas is a default linear gradient. To create a linear gradient, you need to specify the colors to use and the positions at which they should change. For example, in the following statement, the object gradient is set to start at the location 55,10 and end at 55,160.

gradient = context.createLinearGradient(55, 10, 55, 160)

Why these coordinates? Well, you must specify the start and end relative to the entire canvas, not to the object being filled. Therefore, I will be drawing a 90×150-pixel rectangle with its top-left corner at location 10,10, and then I choose a start point of 55,10, which is halfway along the top of the rectangle, and an end point of 55,160, which is halfway along the rectangle’s bottom edge.

Images

The reason that the gradient start and end locations are relative to the canvas and not to objects being filled is to allow you greater subtlety and the ability to create a gradient that covers the entire canvas (or as much or little as you like), and of which only the part existing underneath an object being filled is revealed. This, for example, would enable you to create a gradient that represents a sunset and then draw the inside of a car and use the gradient fill on the windows to reveal the correct parts of the outside gradient for the positions of the windows.

Now that the linear gradient object is created, it is necessary to choose the start and end colors, as with the following two lines, which set an initial stop position (as it is known) of the color #FFF (white), and an end of #000 (black). This is achieved using the addColorStop() function, which is fully explained a little further on, as follows:

Images

What these two calls do is specify with the first argument to each the position at which the color is to be applied (in this case they are 0 and 1 for the start and end), and the second argument sets the color to apply at each of these positions. This gradient is then applied to the current context using the fillStyle property, and then a 90×150-pixel rectangle is drawn using these fill values:

Images

The result of these commands looks like Figure 10-2, in which you can see the fill fade linearly from white to black starting at the top and ending at the bottom of the rectangle.

Images

FIGURE 10-2 A vertically aligned linear gradient fill

You can change the start and end coordinates for the fill to any other locations. For example, in Figure 10-3 a second rectangle has been filled from left to right by choosing the following values for the call to createLinearGradient():

gradient = context.createLinearGradient(110, 85, 200, 85)

Images

FIGURE 10-3 A horizontally filled rectangular gradient has been added.

These coordinates specify a start point halfway down the rectangle’s left edge, and an end that is halfway down its right edge, as used by this fillRect() call:

context.fillRect(110, 10, 90, 150)

In fact, you can choose any start and end location (within or without the area to be filled) as, for example, with this code, which creates a diagonal gradient from top left (210,10) to bottom right (300,160), as shown in Figure 10-4.

Images

Images

FIGURE 10-4 A new rectangle is added with a diagonal gradient fill.

The createRadialGradient() Function

You can also create a gradient that expands radially. That is, it starts at a point and has a certain radius, and then ends focused around another point, with a different (or the same) radius.

For example, the following call to createRadialGradient() specifies an initial location at the center of a rectangle and a width of 0 pixels. The second pair of coordinates remains the same, but with a radius of 45 pixels, so that the gradient starts in the center and continues to the left and right edges. As you can see in Figure 10-5, the top and bottom of the rectangle are outside the radius and so are provided with the color applied to the final stop, which is black:

Images

Images

FIGURE 10-5 The fourth rectangle features a radial gradient.

So that you can see the effect of using start and/or end coordinates that are outside the area being filled, I have increased the radius of the second part of the gradient in Figure 10-6 to 150 pixels, so that it extends past all the rectangle’s edges, like this (as shown in Figure 10-6):

gradient = context.createRadialGradient(355, 85, 0, 355, 85, 150)

Images

FIGURE 10-6 The radius of the gradient fill has been substantially increased.

Images

The second radius value of 150 pixels creates a circle with a diameter of 300 pixels. But note that although this circle extends beyond the area being filled and well into the previous rectangle, the other rectangle is not affected. This is because the gradient applies only to future fills, and not to any pre-existing fills.

The addColorStop() Function

Now that you’ve seen how to create two different types of gradient fills, let’s look at how to modify these to stretch areas of a color and provide nonlinear fills, and to also incorporate colors.

The way to do this is to modify the values passed to the addColorStop() function, and to add more of them to create in-between steps. For example, here’s the code that created the first rectangle in Figures 10-2 to 10-6:

Images

The two lines of importance are the second and third, in which the position is either 0 or 1 (for the start and the end) and the two colors of #FFF (for white) and #000 (for black), which I will now change as follows, to create the rectangle shown in Figure 10-7:

Images

Images

FIGURE 10-7 This linear gradient smoothly changes from red to yellow.

Images

I used both types of color values supported by the addColorStop() function; a hexadecimal string (in this instance three digits, but it could have been six), and a color name (in this case yellow).

Now let’s modify the gradient applied to the second rectangle used in the previous examples, by keeping it grayscale, but adding an additional stop point and color value:

Images

Here, in the second line, a very dark gray color with the value #555 has been applied at position 0.2, which is only 20 percent into the gradient. This forces the left 20 percent to quickly fade from #FFF to #555, and then the remaining 80 percent fades more slowly from #555 to #000, as shown in Figure 10-8.

Images

FIGURE 10-8 The first 20 percent of the gradient fades far more quickly than the final 80 percent.

You can include more stops if you like, and they can be any colors you like. So I have chosen to use a rainbow of colors for the third rectangle, like this, with the result shown in Figure 10-9:

Images

Images

FIGURE 10-9 A rainbow of colors is applied to the third rectangle’s gradient fill.

And remember that all these fills apply equally well to radial gradient fills, so I have chosen to reapply the same rainbow gradient used in the third rectangle to the fill in the final rectangle (but with a radius of 75 pixels to allow the circle to touch the top and bottom edges and show more of the fill), with the result shown in Figure 10-10.

Images

FIGURE 10-10 The rainbow gradient fill is applied radially to the final rectangle.

Using Patterns

In the final part of this lesson I’ll show you how to use patterns on an HTML5 canvas, which you can apply instead of a plain or gradient fill by simply modifying the details you pass to the fillStyle property, and using the same fillRect() or other fill functions.

The createPattern() Function

To create a pattern, you need to supply a pre-existing image such as a jpeg, png, or gif file, and the type of repetition to use when applying the fill, out of the following options:

repeat Repeat the image both vertically and horizontally.

repeat-x Repeat the image horizontally.

repeat-y Repeat the image vertically.

no-repeat Do not repeat the image.

For example, the following code loads in the image smiley-50.png and then uses it as a fill for the first rectangle:

Images

This code requires some explaining (especially if you are new to JavaScript). What is happening is that in the first line a new object called image is created using the JavaScript Image() function and the keyword new. This new object then has the value of its src attribute set to smiley-50.png, which is a file already saved into the same folder.

Then the onload event of the image has a function attached to it. But what does this mean? Well, the image object has various attributes such as its width and height, the source from where it is loaded and, in this instance, onload. However, the onload attribute is known as an eventbecause it is handled in a special manner such that only when the image has been fully loaded from its source is the event called.

To handle the event when it is called, a function is attached that will access the canvas and do the pattern filling. Within the function (inside its curly braces), there are three lines of code, and here you should be back in familiar territory, because the first one is simply a call tocreatePattern() specifying the image object and a value of repeat, indicating how the image should be used, the result of which is placed in the new object called pattern.

The final two lines simply apply this pattern object to the fillStyle property and then call the fillRect() function to use that fill on a rectangle (whose top-left corner is at 10,10) and with a width of 90 pixels and height of 150 pixels. The result is shown in Figure 10-11.

Images

FIGURE 10-11 The rectangle has been filled with a repeating smiley image.

Images

If the function is not attached to the image’s onload event, and the code is simply called from outside of the function, then you run the risk that the image may not be fully loaded when you make the call to the fill command, and therefore the call may fail. This is a standard issue with JavaScript and external images that you must always consider, and so wherever such an image is loaded in, you are recommended to attach the code that will use it to the onload event of the image.

In the figure you can see that the first smiley image is not fully within the rectangle. This is because the fill area is considered to be the entire canvas, and therefore the fill commences at the top left of the canvas (location 0,0), but is only revealed within the constraints of the fill area.

Using the value of repeat-x for the repetition results in Figure 10-12, repeat-y results in Figure 10-13, and no-repeat results in Figure 10-14.

Images

FIGURE 10-12 The rectangle has been filled only horizontally.

Images

FIGURE 10-13 The rectangle has been filled only vertically.

Images

FIGURE 10-14 Only a single instance of the image has been used for the fill.

Summary

At this point you already have substantial ability to work with the HTML5 canvas, and will be able to draw on these concepts in the following lesson, which moves on to writing text (including using gradients and pattern fills), drawing lines and curves, drawing with images, and more.

Self-Test Questions

Test how much you have learned in this lesson with these questions. If you don’t know an answer, go back and reread the relevant section until your knowledge is complete. You can find the answers in the appendix.

1. Which function is used to create a filled rectangle?

2. How can you change the fill color?

3. How can you draw a clear rectangle?

4. With which function can you draw a rectangular outline?

5. How can you create a linear gradient?

6. How do you create a radial gradient?

7. How do you specify the colors in a gradient?

8. With which function can you use an image for a pattern fill?

9. What are the four different types of pattern fill?

10. How do you ensure an image has been loaded before you use it?