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.

Figure 8-1  Matrix parameters and positions

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.

Figure 8-2  Reflected text

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

Figure 8-3  Reflection with scale and gradient

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.

Figure 8-4  The identity matrix

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.