Matrix transforms based on an arbitrary registration point
Posted by: Keith H in ActionScript 3, Flash 9, tags: Arbitrary, Matrix, Registration Point, Skew, TransformI was wanting a lightweight function to resize, rotate, and skew DisplayObjects based on a dynamic registration point so I made a function to apply my desired matrix settings.
One thing that bothers me is that I could not figure out how to skew along the X and Y axis at the same time. When I do set "c" and "b" Matrix properties, one of the skewed axis does not skew parallel like it should. And if I concatenate separate skew Matrices, the last concatenated skew Matrix transforms correctly but not the one before it. I'm trying to avoid using nested DisplayObjects to perform the separate X and Y skews, but that looks like an option I will have to use.
/*--------------------------------------------------------------------------- Sets the transform property of DisplayObject with a customized Matrix. display -An ActionScript DisplayObject. tx -Translation x. ty -Translation y. reg -Registation point from which all transform effects orient from. ang -Rotation in in degrees. scalex -X scale percentage. scaley -Y scale percentage. skew -Skew percentage of the DisplayObjects width or height. axis -String indicating which axis to skew on. Note: -The "skew" argument only works one axis at a time, If anyone knows how to skew on both X and Y axis at the same time accurately please help me. -The "reg" Registration point get scaled by scalex and scaley. ----------------------------------------------------------------------------*/ function setDisplayMatrix(display:DisplayObject, tx:Number=0, ty:Number=0, reg:Point=null, ang:Number=0, scalex:Number=1, scaley:Number=1, skew:Number=0, axis:String="x"):void { reg=reg||new Point(); var curM:Matrix=new Matrix(); var skewM:Matrix=new Matrix(); var rotM:Matrix=new Matrix(); var scaleM:Matrix=new Matrix(); var rp:Point; var r:Number=ang*Math.PI/180; if(axis == "y"){ skewM.c=Math.tan(skew); }else{ skewM.b=Math.tan(skew); } scaleM.scale(scalex,scaley); rotM.rotate(r); curM.concat(scaleM); curM.concat(skewM); curM.concat(rotM); rp=curM.transformPoint(reg); curM.tx=-rp.x; curM.ty=-rp.y; curM.tx+=tx; curM.ty+=ty; display.transform.matrix=curM; }
Here is a diagram I made to show what kind of skew I wanted to achieve instead of only skewing one axis at a time:

Entries (RSS)
not sure if this is what you need, but try:
…
skewAmount:Number=0;
…
skewM.c=skewM.b=Math.tan(skewAmount);
…
It performs skew on both axis in the same time
simple, direct and clean. Thanks!
Thanks Flanture, but I may be describing the kind of skew I want to do incorrectly. I would like to skew a separate value along the horizontal edge of the shape, and also skew a separate value along the vertical edge of the shape. I’ve updated this post with a diagram showing the kind of skew I’d like to do.
To make the skewing run along the edges is what I wish to do. After skewing along the horizontal axis first, the vertical axis is different. Visa versa if I skewed along the vertical axis first.
Hello Keith,
This is an astonishingly good post and fantastic working example…
Would you be willing to post a link to the source code for this, as it would be most appreciated?
Kind regards,
Matthew