Quicktip: Skewing an image using ActionScript 3


So you want to skew an image, or a MovieClip or perhaps any other DisplayObject. You could do this manually in the Flash editor of course, but what if you need to do it dynamically, or in Flex.. Here is how.
//If you prefer to draw one visually, skip down
/*var target:MovieClip = new MovieClip();
target.graphics.beginFill(0x000000);
target.graphics.lineTo(100,0);
target.graphics.lineTo(100,100);
target.graphics.lineTo(0,100);
target.graphics.lineTo(0,0);
target.graphics.endFill();
//center it on the stage
target.x = stage.stageWidth *.5-50;
target.y = stage.stageHeight *.5-50;
//add the mc to the stage
addChild(target);*/
/*****/
//Set the skewing angle
var degX:Number = 15;
var degY:Number = 15;

//Get the transform matrix for the object to skew
var m:Matrix = target.transform.matrix;
m.b = Math.tan(degY *(Math.PI/180));
m.c = Math.tan(degX +(Math.PI/180));

//Apply the matrix to the transform object
var t:Transform = new Transform(target);
t.matrix = m;

//Apply the skew
target.transform = t;

Looks like a lot of code, but remember that the first 10 lines of code(not counting comments) are just to draw a MovieClip onto the center of the stage. The actual skew is achieved in just 8 lines of code.
When applying this to a movieclip it will look something like the image in the top of the post.

9 comments:

fab said...

how to make a skewing motion using this technique. I want a rectangle that skews for 3 seconds, then stop.

fab said...

Hah, I know it already.

I'll share my code with you, skewing and resizing:

loop this function to skew in motion:

private function skewingMotion(angleX:Number, angleY:Number):void
{
if(angleX < currentAngleX)
{
skew(currentAngleX--,0);
}
else if(angleX > currentAngleX)
{
skew(currentAngleX++,0);
}

if(angleY < currentAngleY)
{
skew(0,currentAngleY--);
}
else if(angleY > currentAngleY)
{
skew(0,currentAngleY++);
}
}

where skewing is done by:

private function radiansToDegrees(radians:Number):Number {
return (radians * (180 / Math.PI));
}

private function degreesToRadians(degrees:Number):Number {
return (degrees * (Math.PI / 180));
}

public function skewTransform(angleX:Number, angleY:Number, target:DisplayObject):void
{
degX = angleX;
degY = angleY;

m = target.transform.matrix;

//Apply the matrix to the transform object
m.b = Math.tan(degreesToRadians(degY));
m.c = Math.tan(degreesToRadians(degX));

t= new Transform(target);
t.matrix = m;

//Apply the skew
target.transform = t;
}

Anonymous said...

This is very useful. Thank you for posting this!

Also, I noticed a little error. This line,

m.c = Math.tan(degX +(Math.PI/180));

is supposed to be written like this, if I'm not mistaken:

m.c = Math.tan(degX *(Math.PI/180));

All I did was change the plus sign to a multiplication sign.

Once again, thanks!

faithiology said...

how can this work in flash

Matthew Akingbade said...

THANK YOU

Anonymous said...

This is kinda reviving an old thread, but is it possible to rotate a rectangle and extend it to the location of a mouse click while still maintaining the angles of the rectangle using AS3?

For example, say I have a rectangle with a registration point of center bottom. Say I want it to rotate with a mouse look (already have that coded), and when the left mouse button is pressed, I want the rectangle's "top" edge to extend to the mouse click location, while maintaining the 90 deg angles (relative to the rectangle, not the stage).

Jørn Kinderås said...

Sure you can have an object (rectangle) extend to the mouse position. Simply get the distance from the top of your object to the mouse click position and extend the height of your object accordingly.

Anonymous said...

Do you have any idea why I gather Java fault warning while loading your site in IE 6?

As a final note , permit me thank you for your tolerance with my English as (I am confident you have figured this by now,), English is not my head tongue hence I am utilizing Google Translate to build out what to record what I genuinely mean to write down .

Jørn Kinderås said...

IE 6.. don't use that! Ever! There is absolutely no logical reason to use IE 6 in the year of 2011.