Matrix Transforms
Rotation, translation, and scaling are all accomplished using a transformation matrix—a set of nine numbers that are used to transform a two-dimensional array, such as a bitmap, using linear algebra.
There are convenience methods for the most common transforms—rotation, translation, and scaling—but you can use matrix transforms to achieve other effects as well, such as shearing or reflection.
Setting the Transformation Matrix
You can set the transformation matrix to new values by calling the context’s setTransform(a, b, c, d, e, f)
method, passing in new values for the first two rows of the matrix (the third row is always 0 0 1
).
The position of the parameters in the matrix is shown in Figure 8-1.
When you set the transformation matrix, it overrides any rotation, translation, or scale settings, as these settings all use the transformation matrix.
Example: Setting the Matrix for Reflection
To set the transformation matrix to reflect everything around the y-axis, call ctx.setTransform(1, 0, 0, -1, 0, 0)
. Thereafter, all drawing operations result in an upside-down image, and all y-coordinates are multiplied by -1.
To set up a transformation matrix to reflect everything around the x-axis, call ctx.setTransform(-1, 0, 0, 1, 0, 0)
. Thereafter, all drawing operations result in a mirror image, and all x-coordinates are multiplied by -1.
To set up a transformation matrix to reflect everything around both the x-axis and y-axis, call ctx.setTransform(-1, 0, 0, -1, 0, 0)
. Thereafter, all drawing operations result in an upside-down mirror image, and all x and y-coordinates are multiplied by -1.
An example of text reflected around the y-axis is generated by Listing 8-1 and shown in Figure 8-2.
Listing 8-1 Reflecting text
<html> |
<head> |
<title>Reflection Matrix</title> |
<script type="text/javascript"> |
var can, ctx; |
function init() { |
can = document.getElementById("can"); |
ctx = can.getContext("2d"); |
ctx.fillStyle = "blue"; |
ctx.font = "48pt Helvetica"; |
ctx.fillText("Reflection", 0, 100); |
ctx.setTransform(1, 0, 0, -1, 0, 0); |
ctx.fillStyle = "red"; |
ctx.fillText("Reflection", 0, -100); |
} |
</script> |
</head> |
<body onload="init()"> |
<canvas id="can" height="200" width="300"> |
</canvas> |
</body> |
</html> |
You can set the scale after setting a reflection matrix, because the two operations use different parts of the matrix. Listing 8-2 adds a few lines to the previous example that set the y-scalar to 1.5 and sets the fill style to a gradient instead of a solid color, making the reflection taller and fading it from blue to transparent white. The result is shown in Figure 8-3
Listing 8-2 Adding a scalar and gradient
ctx.scale(1, 1.5); |
var grad = ctx.createLinearGradient(0, -50, 0, -140); |
grad.addColorStop(0, 'blue'); |
grad.addColorStop(1, 'rgba(255, 255, 255, 0)'); |
ctx.fillStyle = grad; |
ctx.fillText("Reflection", 0, -102 / 1.5); |
The Identity Matrix
To reset the transformation matrix to the identity matrix (no transformation), call ctx.setTransform(1, 0, 0, 1, 0, 0)
. The identity matrix and the parameter positions are illustrated in Figure 8-4.
Transforming the Transformation Matrix
The transformation matrix can be treated as a two-dimensional array. You can transform the current matrix by applying a second matrix to it.
To transform the current matrix by a second matrix, call the context’s transform(a,b,c,d,e,f)
method, passing in values for the first two rows of the second matrix (the third row is always 0 0 1).
Transforming the transformation matrix potentially changes any rotation, scale, or translation settings.
Setting the rotation, scale, or translation after transforming the transformation matrix results in additional changes to the matrix—the matrix values used by the rotation, scale, or translation operation are overridden.
Transforming the transformation matrix is a method intended for developers well-versed in linear algebra. A description of the mathematics involved falls outside the scope of this document.
Copyright © 2013 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2013-09-18