# Transformation Matrix

### Transformation Matrix

The logical place to start the discussion on matrices is with the class flash.geom.Matrix. As I mentioned in the previous section, the class name Matrix is misleading because it does not represent a generic matrix, but rather a transformation matrix that’s applied directly to the MovieClip and BitmapData instances (and can also be used to transform point objects). It allows manipulation of these instances in the form of translation (*x*, *y* position), scale, rotation, and skew. Because of this fact, I will use the term “transformation matrix” interchangeably with the class name Matrix (note the leading capital letter specifying the class and not matrices in general) for the remainder of this article.

Now you might be thinking, “I can do most of these transformations code without matrices so what’s the benefit?” There are at least four good reasons to use the transformation matrix:

- Skewing is not available in ActionScript outside of the transformation matrix
- BitmapData requires a transformation matrix to transform drawn bitmaps
- You can use a transformation matrix to encapsulate information about how to transform a MovieClip/BitmapData instance and then use it over and over again
- You can concatenate matrices to combine their geometric effects

Figure 3 shows the values represented in a transformation matrix. Although this is a 3 x 3 matrix, Flash uses default values for *u*, *v*, and *w* (in gray) as 0, 0, and 1 respectively—which effectively makes it a 2 x 3 matrix. Each value in this matrix has a very specific effect on the transformation of a MovieClip or BitmapData instance.

**Note:** The matrix represented in Figure 3 is different than the transformation matrix represented in the Flash documentation. I show it this way because, to me, it seems to align with the order of values passed into the Matrix constructor (a, b, c, d, tx, ty). It also allows representation of *x* values in column 1 and *y* values in column 2. Because an array is not passed into the Matrix class at any time, the order of the values in the array isn’t of crucial importance. However, this subtle difference is something to consider.

There are four basic ways to transform a MovieClip/BitmapData instance:

**Translation:**The values “tx” and “ty” in Figure 3 represent the*x*and*y*translation values, respectively, in pixels.**Scale:**The values “a” and “d” represent the*x*and*y*scale values, respectively. A value of 1 indicates 100% of scale.**Skew:**The values “b” and “c” represent the*y*and*x*skew values, respectively. A value of 0 indicates no skew, while a value of 1 indicates a skew value equal to the width or height of the object at a scale of 1.-
**Rotation:**The values “a”, “b”, “c”, and “d” can be used in combination to affect the rotation of an object. For an angle “q”, rotation is achieved in the matrix by using the following values:a = cos(q)

b = sin(q)

c = –sin(q)

d = cos(q)

**Note:** Don’t worry—the Matrix class provides helper methods to make this easy, as described later in this section.

To apply a transformation matrix, start by creating an instance of flash.geom.Matrix, passing in values that represent the desired transformation. Note that the Matrix constructor doesn’t accept an array of values, but rather a set of arguments representing a, b, c, d, tx, and ty respectively. You can also set the values individually after the Matrix instance is created, using Matrix.a, Matrix.b, Matrix.c, Matrix.d, Matrix.tx, and Matrix.ty.

After you’ve set the matrix values, you can do either of the following:

- Set the Transform.matrix value of the MovieClip instance to the newly created matrix to transform that instance
- Pass in the matrix to Bitmap.draw to transform the Bitmap instance

The following example applies 200% *x* and *y* scale and moves a MovieClip instance to _x = 100 and _y = 50:

import flash.geom.Matrix;

// Scale to 200% and move to _x = 100 and _y = 50:

var m:Matrix = new Matrix( 2,0,0,2,100,50 );

clip.transform.matrix = m;

Another benefit to transformation matrices is that you can combine multiple transformation types into a single matrix. You can also have multiple matrices each with one or more transformations applied, and then combine (multiply) them to achieve a combined effect. Matrix multiplication is achieved between transformation matrices using Matrix.concat.

For instance, if you wanted to move a MovieClip instance five pixels to the right of its current location on each frame, you could use concatenation:

import flash.geom.Matrix;

// create a matrix that moves to _x = 5:

var m:Matrix = new Matrix( 1,0,0,1,5,0 );

onEnterFrame = function() {

// Use a copy of the original matrix so its values aren't affected:

var move:Matrix = m.clone();

// Multiply this matrix with the matrix of the clip:

move.concat(clip.transform.matrix);

// Apply the matrix to the clip:

clip.transform.matrix = move;

}

As you can see in this example, if you want to affect multiple transformations on an instance, this is a cleaner way to do it, rather than independently updating _x, _y, _xscale, _yscale, and _rotation.

To apply a transformation matrix to a BitmapData instance, you can pass it directly into the Draw method. In the following example, a MovieClip instance is drawn onto a BitmapData instance as you move the mouse and is positioned properly using the transformation matrix:

Additionally, the Matrix class implements methods that make it easy to apply transformation changes to the matrix. These include the following:

- Matrix.translate(tx:Number, ty:Number)
- Matrix.scale(sx:Number, sy:Number)
- Matrix.rotate(angle:Number)
- Matrix.createBox(scaleX:Number, scaleY:Number, rotation:Number, tx:Number, ty:Number)

After applying changes to a matrix, you can always view the resulting matrix values by using this method:

- Matrix.toString();

The transformation matrix has another useful feature that I haven’t mentioned yet. It provides the ability to transform gradients. A gradient can have its translation, scale, and rotation values affected by Matrix using Matrix.createGradientBox. This allows you to control the width, height, rotation, and *x* and *y* positions of the gradient within the shape that it exists.

Practically speaking, while you still need to create a gradient in ActionScript using MovieClip.beginGradientFill in Flash 8, you can use the Matrix class to define the gradient’s translation, scale, and rotation.

## Comments