Drawing a Frame of Animation

Drawing a Frame of Animation

Before we have a look at the actual animate function implementation, first we will have a look at the things that we should do in a single pass of drawing our animation. To try to explain this clearly, we have broken the process down into six simple steps:

1. Save the canvas context. Saving the canvas context saves information about the current canvas state, which can be restored later. This is particularly important when you are writing code that you want to integrate with other canvas-drawing code. Without saving and restoring canvas state, it would be quite possible to effect the other draw code that is making similar changes.

CHAPTER 7: Exploring Interactivity

2. Clear the background. The first step in drawing an animation frame usually involves clearing the background from what has been drawn in the previous frame. As you become more comfortable with drawing to the canvas, however, you may want to limit doing this to squeeze more performance out of your animations. For what we are doing here, though, clearing the background is ideal.

3. Adjust canvas parameters. Before drawing to the canvas, you may want to change parameters such as stroke or fill style, and also colors.

4. Draw the animation frame. Draw the animation frame using the various canvas methods provided. We’ll look at an example shortly that touches on a few elements of this, but, for further information, the Mozilla Developer Center Canvas Tutorial is an excellent resource ( https://developer.mozilla.org/en/Canvas_tutorial).

5. Perform animation loop logic. It is likely that, to effect any kind of animation, you will need to update variable values, perform calculations, and so on. Generally, within the animation loop is an effective place to perform this kind of logic.

6. Restore the canvas state. Once the animation loop has been completed, restore the canvas state to prevent modifications that have been made to the canvas within the loop (such as changes to fill or stroke style) being used in other parts of the application.

NOTE: While some would suggest that saving and restoring the canvas state is optional depending on your implementation, our advice would be to implement the logic at least in the first instance, as it is the best chance you have of making your code reusable within another application. If for some reason (such as performance optimization) it becomes necessary to remove the state-saving and restoring steps, then do so with care.

A Working Example

With an understanding of the steps that are required in a single pass of the animate function, let’s now have a look at the code:

function animate() {

context.save();

try { // clear the drawing surface

context.clearRect(0, 0, canvas.width, canvas.height);

// set a stroke style

context.strokeStyle = "rgba(68, 221, 255, 0.5)"; context.lineWidth = 4;

// iterate through the drops and draw them to the canvas var ii = 0;

CHAPTER 7: Exploring Interactivity

while (ii < drops.length) {

// draw the drop

context.beginPath(); context.arc(drops[ii].x, drops[ii].y, drops[ii].size, 0, 2 * Math.PI,

false);

context.stroke();

// increase the size of the drop drops[ii].size += 2;

// if the drop has exceeded its max size, then remove it if (drops[ii].size > drops[ii].maxSize) {

drops.splice(ii, 1); } // otherwise, on to the next drop else {

ii++; } // if..else } // while } finally {

context.restore();

} // try..finally } // animate

The code in the animate function creates an animation that will produce a result similar to that shown in Figure 7–4.

Download from Wow! eBook <www.wowebook.com>

Figure 7–4. A snapshot of the animation created by our drops.js file Looking at the preceding code, we can see that all of the items that were outlined

previously have been covered:

CHAPTER 7: Exploring Interactivity

The context.save method is called to save the canvas state as per step 1. We then open a try..finally block to implement steps 2 through 5.

The first call in the inner block is then calling the context.clearRect method to clear the canvas background. This covers step 2 in our process, but, as mentioned earlier, in some cases you may want to remove this to optimize performance.

We then move to step 3, which is adjusting the canvas parameter for drawing the display. In our sample, we are adjusting the strokeStyle and lineWidth parameters of the canvas context. Additionally, note our use of the CSS3 rgba function to specify the strokeStyle (see www.w3.org/TR/css3-color/#rgba-color for more info on the rgba function). The rgba function allows us to provide the red, green, blue, and finally alpha values for the color of the stroke (or fill). This provides us with the ability to create semitransparent lines and fill, which can provide some visually appealing effects.

Then step 4—we draw. In the case of our example, steps 4 and 5 are very much intermingled, which is probably something that will occur in many implementations. Our draw code here is simply drawing circles for each of the drops on the display, but you will probably notice that a simple circle function is nowhere in sight. Instead, we use paths. At first glance, this is a little disconcerting—but don’t worry, you will get used to using paths, and we cover this in a little more detail soon.

Step 5 then follows; as mentioned, this is mixed fairly tightly with step

4, as we are both drawing and updating multiple drops when we are drawing a single frame of animation. In our code, the size of the drop is increased, and, if it reaches a certain size, then it is removed from the drops that we will draw.

Finally, we break out of the try block in the try..finally loop and execute the finally section. The finally section always executes, and in this case it restores the canvas state as per step 6.