Servage Magazine

Information about YOUR hosting company – where we give you a clear picture of what we think and do!

Working with Advanced HTML5 – Part 5

Tuesday, March 11th, 2014 by Servage

Transformations on the canvas refer to the mathematical adjustment of physical properties of drawn shapes. The two most commonly used shape transformations are scale and rotate, which we will focus on in this section.

Under the hood, a mathematical matrix operation applies to all transformations. Luckily, you do not need to understand this to use simple Canvas transformations. We will discuss how to apply rotation, translation, and scale transformations by changing simple Canvas properties.

Rotation and Translation Transformations

An object on the canvas is said to be at the 0 angle rotation when it is facing to the left. (This is important if an object has a facing side; otherwise, we will use this as a guide.)

Consequently, if we draw an equilateral box (all four sides are the same length), it doesn’t have an initial facing side other than one of the flat sides facing to the left. Let’s draw that box for reference:

//now draw a red square
context.fillStyle = "red";
context.fillRect(100,100,50,50);

Now, if we want to rotate the entire canvas 45 degrees, we need to do a couple simple steps. First, we always set the current Canvas transformation to the “identity” (or “reset”) matrix:

Transformations are applied to shapes and paths drawn after the setTransform() or other transformation function

If you use this code verbatim, you will see a funny result…nothing! This is because the setTransform() function call affects only shapes drawn to the canvas after it is applied. We drew our square first and then set the transformation properties. This resulted in no change (or transform) to the drawn square.

Simple rotation transformation

function drawScreen() {
//now draw a red square
context.setTransform(1,0,0,1,0,0);
var angleInRadians = 45 * Math.PI / 180;
context.rotate(angleInRadians);
context.fillStyle = "red";
context.fillRect(100,100,50,50);
}

zzz

We get a result this time, but it will probably differ from what you expect. The red box is rotated, but it looks like the canvas was rotated with it. The entire canvas did not rotate, only the portion drawn after the context.rotate() function was called. So, why did our square both rotate and move off to the left of the screen? The origin of the rotation was set at the “nontranslated” 0,0 position, resulting in the square rotating from the top left of the entire canvas.

We must “translate” the point of origin to the center of our shape to rotate it around its own center

Let’s change the earlier example to rotate the red square 45 degrees while keeping it in its current location.

First, we take the numbers we applied to the fillRect() function call to create a few variables to hold the red square’s attributes. This is not necessary, but it will make the code much easier to read and change later:

var x = 100;
var y = 100;
var width = 50;
var height = 50;

Next, using the context.translate() function call, we must change the origin of the canvas to be the center of the red square we want to rotate and draw. This function moves the origin of the canvas to the accepted x and y locations. The center of our red square will now be the desired top-left corner x location for our object (100), plus half the width of our object. Using the variables we created to hold attributes of the red square, this would look like:

x+0.5*width

Next, we must find the y location for the origin translation. This time, we use the y value of the top-left corner of our shape and the height of the shape:

y+0.5*height

The translate() function call looks like this:

context.translate(x+0.5*width, y+0.5*height)

Now that we have translated the canvas to the correct point, we can do our rotation.

The code has not changed:

context.rotate(angleInRadians);

Finally, we need to draw our shape. We cannot simply reuse the same values from example because the canvas origin point has moved to the center of the location where we want to draw our object. You can now consider 125,125 as the starting point for all draw operations. We get 125 for x by taking the upper-left corner of the square (100) and adding half its width (25). We do the same for the y origin position. The translate() method call accomplishes this.

We will need to draw the object starting with the correct upper-left coordinates for x and y. We do this by subtracting half the width of our object from the origin x, and half the height of our object from the origin y:

context.fillRect(-0.5*width,-0.5*height, width, height);

Why do we do this? The output illustrates this.

Consider that we want to draw our square starting at the top-left corner. If our origin point is at 125,125, the top left is actually 100,100. However, we have translated our origin so that the canvas now considers 125,125 to be 0,0. To start our box drawing at the nontranslated canvas, we have to start at −25,−25 on the “translated” canvas.

This forces us to draw our box as though the origin is at 0,0, not 125,125. Therefore, when we do the actual drawing of the box, we must use these coordinates, as shown in the example.

cx

Sources for further reading

Working with Advanced HTML5 - Part 5, 5.0 out of 5 based on 1 rating
Categories: Guides & Tutorials

Keywords:

You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

No comments yet (leave a comment)

You are welcome to initiate a conversation about this blog entry.

Leave a comment

You must be logged in to post a comment.