Most often, questions are asked about how to scale a DisplayObject, and the answer is usually to use a Matrix.
My question is, how to you GET the scale of a Matrix (
you have access to the matrix object's a
and d
public properties, which represent the scaling of the x-axis and y-axis respectively:
package
{
//Imports
import flash.display.Sprite;
import flash.geom.Matrix;
import flash.display.Shape;
//Class
public class Test extends Sprite
{
//Constructor
public function Test()
{
var sh:Shape = new Shape();
sh.graphics.beginFill(0xFF0000, 1.0);
sh.graphics.drawRect(0, 0, 100, 100);
sh.graphics.endFill();
var scaleMatrix:Matrix = new Matrix();
scaleMatrix.scale(4, 6);
sh.transform.matrix = scaleMatrix;
addChild(sh);
trace("Matrix X Scale: " + scaleMatrix.a, "\nMatrix Y Scale: " + scaleMatrix.d);
}
}
}
// Matrix X Scale: 4
// Matrix Y Scale: 6
Generally, a reliable way to isolate the scaling component in a matrix is to use the matrix in question to transform the unit vectors along the axes, and then measure the length of the resulting vectors.
For instance, given the transform
from a DisplayObject, and using the Matrix3D, the scaleX
would be obtained as follows:
transform.matrix3D.deltaTransformVector(Vector3D.X_AXIS).length
Or, if you use the concatenated 2D Matrix, the scaleY
would be:
transform.concatenatedMatrix.deltaTransformPoint(new Point(0,1)).length
Note that the deltaTransform*
functions ignore the translation effects of the matrices, which have no effect on the scaling.
You can get the x and y scales of a matrix even when it's rotated.
Here's the code:
public static function getScaleX(m:Matrix):Number
{
return Math.sqrt(Math.pow(m.a + m.b, 2));
}
public static function getScaleY(m:Matrix):Number
{
return Math.sqrt(Math.pow(m.c + m.d, 2));
}
Explanation:
I've found that it's easier to think of A B C D
as points that define the x and y axes in the transformed coordinate space. A, B
is the position of the first point of the transformed x axis (an identity matrix has these as 1, 0
, which will not transform), and C, D
is the position of the first point of the transformed y axis (identity values of 0, 1
).
If we have a matrix that will scale the x axis by 2 then A, B
will be 2, 0
. The rest of the points on x axis will be this same distance away from the last (so 2 points away from the last).
If we have a matrix that will rotate 90 degrees clockwise then A, B
will be 0, 1
(pointing the x axis along the positive side of the y axis) and C, D
will be -1, 0
(pointing the y axis down the negative side of the x axis).
The scale of the x axis is the distance to the first point. In the scenarios that I've mentioned the scale is easy to find. In the previous example A, B
is 0, 1
so the scale is 1. If rotation is not on at a 90 degree increment then you can find the length of the line segment from 0, 0
to A, B
by using the Pythagorean theorem: sqrt(a^2 + b^2) = c. This is what my code is doing.
Hope this helps someone.