Workbook 2, Page 4: Animation and Interaction with Canvas

Back on page one we saw animation with Canvas and SVG, and interaction with SVG. Now we will look at animation and interaction with Canvas in more detail.

The tricky thing is that with Canvas, we don't store the objects. That means we don't have anything to change - it's up to the program to keep track of things and adjust them accordingly. Similarly, for interactions, there are no objects to generate events. The graphics "objects" only exist in our program, so we are responsible for creating events.

We'll look at some implications of needing to represent objects in our own programs on this page.

Box 1: Animation with Canvas

When we animate, we need to change the image for each "frame". With SVG, we modify the elements that change - and the picture gets updated accordingly. With Canvas, we have to update the picture ourselves.

In general, we will do this by (1) clearing the canvas and (2) redrawing everything. Notice that this is wasteful: we redraw things that didn't change. If we really care about performance, we would try to figure out what changed and only change those parts. With graphics, figuring out what changed and only changing those parts can be hard (especially with 3D). For example, moving one object might let us see new things behind. The complexity of keeping track of what has changed may outweigh the extra effort to redraw things that didn't change.

In almost all cases in this class, we will just clear the whole canvas and draw everything. We'll just be careful to try to make "drawing everything" as fast as possible (which can be easier, since we don't need to think about what not to draw).

So, if you notice that things are wasteful, you're being observant.

Here's an example (that we will come back to later):

Notice that we can use the same animation loop for both elements. Notice how for the Canvas, we clear the canvas and redraw everything. For SVG, we only change the things that move (it may or may not decide to redraw everything)

Box 2: Events for Canvas

With SVG, because the graphics elements are HTML element, we can assign events to them. In this example, I will handle all the onclick events for each of the objects. (try clicking on the rectangles - you can even click on the moving one!).

With Canvas, this is much trickier, because the only element is the Canvas element itself! We need to figure out where the mouse is, and then check each object to see if it should get the event, and then do the appropriate thing.

To make this easier, we'll change how we write the code. If you look at the drawing function for box1, the rectangles are not actually represented (except in the code). Instead, we'll make objects for each rectangle so we'll have a list of them. We'll use this list for drawing, and we'll also use this list for doing other things.

The list of objects is sometimes called a display list.

While the display list idea is simple - keep a list of graphics objects - it is worth looking at the implementation since it uses a lot of JavaScript tricks.

If you look at the code, you'll see a drawing routine that takes a list of rectangles - and draws them all. The rectangles are stored as JavaScript objects - which might seem a little weird if you're used to objects in languages like Java or C++. These are generic objects - we never define a class. We just stick the member values we want into them. So, for example, the line:

box2rects.push({"x":0,"y":35,"w":20,"h":20,"color":"black"});

makes a new rectangle object (with x=0, y=35, etc.) and puts it at the end of the box2rects array.

Once we have the display list, it is relatively straightforward to get the desired event behavior. We have one event handler for the Canvas element. This has to figure out where the mouse is (which requires us to know where the Canvas element is). The function clickRectList then checks this position against all of the rectangles.

Fortunately, all of the objects are rectangles, and checking to see if the mouse position is inside of them is easy

This code is a little bit tricky - so take the time to understand it.

Box 3: Interaction without events

As long as we have an animation loop running, we can get by without events for some things by polling: checking the input device on every iteration.

Move the mouse around inside this canvas:

And of course, don't forget a

Make sure you understand that example (including transparency), but here's a different version (try clicking):

Be sure to understand how this works - including how we know if the mouse is pressed. Notice how each rectangle not only stores it's position, but also its velocity. And also notice that rectangles do get removed - we don't just keep making more.

You will be required to use all of these ideas on the next page.

Summary: Interaction and Animation with Canvas

There are a few big ideas on this page:

  1. We make display lists to represent graphics objects. If the underlying API does not do it for us, we have to manage it ourselves.
  2. The web browser likes to work in an event-driven model. If we want to do things in a polling (animation-loop) style, we have to adapt.

These are concepts we'll use a lot as we make more complicated graphics programs.

Make sure you understand the code! It not only shows the concepts, but it also uses a lot of JavaScript idioms.

On the next page we'll let you try doing some of this stuff on your own.