The last article demonstrated a basic implementation of the canvas element where an image was moved across the screen. While it was a simple example, the same effect could just as easily been achieved by modifying the properties of a handful of standard HTML elements like an IMG or DIV. Here we will tap into some of the more advanced functions of the canvas element to demonstrate some of its real power.
The only change made to the HTML file is the addition of a few buttons. When clicked these button set the currentFunction variable (described later), changing which function is run during the render loop.
FPS The target frames per second
SECONDSBETWEENFRAMES The number of seconds between each frame (which is the inverse of the FPS value)
HALFIMAGEDIMENSION Half of the width / height of the image we are drawing, which is used to position the image in the center of the canvas
HALFCANVASWIDTH Half of the width of the canvas, used in conjunction with HALFIMAGEDIMENSION to center the image in the canvas
HALFCANVASHEIGHT Half of the height of the canvas, used in conjunction with HALFIMAGEDIMENSION to center the image in the canvas
currentFunction The function to be run during the render loop
currentTime The time in seconds that the application has been running
sineWave A value between 0 and 1, used to animate the image
image The image to be drawn to the canvas
canvas A reference to the canvas element
context2D A reference to the 2D context of the canvas element
There will be four effects demonstrated: modifying the alpha (or transparency), scaling, rotating and shearing the image. In order to show these effects in action we need to be able to apply the changes they make over a range of values. The sineWave variable will be used to define the base of this value range.
The standard sine function produces a nice wave graph with values between -1 and 1. First of all we increase the currentTime variable to reflect how long the application has been running for, and then use that value to find a point on the sine wave. By adding 1 and diving by 2 we can take the values returned by the sin function, which are between -1 and 1, and convert them into values between 0 and 1. [code]
The canvas is then cleared with a call to clearRect, making sure we have a clean slate to work with. [code]
Effects applied to the canvas are cumulative. This allows effects to be "built up" from a handful of simple functions. For example you may have a space ship that you want to rotate, translate and scale before drawing to the screen. Since the effects are applied at the canvas level though these effects are applied to everything being drawn to the canvas, not just your one image or shape (like a space ship).
The save and restore functions in the context provide an easy way to apply these cumulative effects, draw an image or shape to the canvas that has these effects applied, and then "undo" the changes. Behind the scenes the save function pushes the current drawing state onto a stack, while the restore function pops the last state off the stack. So, using the example of a space ship above, you would perform the following operations:
- Call the save function (which saves the current drawing state)
- Rotate, translate and scale the context
- Draw the ship
- Call the restore function to remove any effects that might have been added since the last call to save, effectively undoing those changes
We use this combination of the save and restore functions by first saving the drawing state before any effects are applied to the canvas. [code]
Once the drawing state is saved it’s time to actually apply the effects that are the purpose of this demo application. First we call the translate function, which has the effect of centering the image that will be drawn in the canvas. [code]
Next the function referenced by the currentFunction variable is called. It is in these referenced functions that the alpha (or transparency), scaling, rotating and shearing of the image takes place. These functions will be described later. [code]
Once the effects have been applied the image has to be drawn to the canvas. We use the drawImage function to achieve this. [code]
And finally any effects that have been applied since the call to the save function are removed from the canvas by calling the restore function. [code]
By modifying the globalAlpha property of the context, the transparency of any subsequent drawing operations is altered. Setting globalAlpha to 0 means that any objects drawn will be completely transparent, while setting the value to 1 means any drawing operation retains it’s original transparency levels. Modifying the globalAlpha variable here fades the smiley face in and out.
Shearing is achieved by applying a matrix to the canvas through the transform function. Transformation matrices are a topic of their own, but you can find a number of standard 2D transformation matrices on the web, and these can be applied using the transform function without needing any real understanding of the math involved. Shearing effectively pushes the top or bottom of an image across to one side.
As it’s name suggests the scale function modifies the size of the image. You will notice that we also make an additional call to the translate function. This is to keep the scaled image in the center of the canvas element. If you comment out this line of code you will see that the scaled image appears to grow to the right and bottom from the top left corner. The translate call compensates for this, and keeps the image centered.
Like the scale function, the rotate function does exactly as it’s name suggests: it rotates the image. And like the scale function some additional calls to the translate function have to be made to ensure that the image is rotated around it’s center rather than the top left corner. I encourage you to comment out the calls to the translate functions to see the difference they make for yourself.
What we have seen here are four fairly simple effects that can be easily applied using the canvas element, but would be next to impossible to apply using standard HTML elements. Some of these effects can be achieved using the built in functions like scale and rotate, while the transform function allows for a huge range of image manipulations (shearing being just one).