Somebody recently asked on a forum how you could rotate images using the Matrix class. I quickly built this super-simple little example which shows how to use the <mx:Rotate /> effect as well as the Matrix class’s rotate() method.
Full code after the jump.
If you’re new to transforms and matrices, check out Senocular.com’s excellent article, “Understanding the Transform Matrix in Flash 8“.
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/09/14/rotating-images-using-the-matrix-class/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="horizontal"
verticalAlign="middle"
backgroundColor="white">
<mx:String id="deg">°</mx:String>
<mx:Script>
<![CDATA[
import mx.core.UIComponent;
private function img1_effectEnd():void {
/* Set the appropriate Label text. */
lbl1.text = "img1.rotation = " + img1.rotation.toString() + deg;
}
private function img2_creationComplete():void {
/* "Copy" the existing matrix. */
var m1:Matrix = img2.transform.matrix;
/* Rotate the matrix 45 degrees (note that we have to
convert from degrees to radians since the rotate()
method expects radians. */
m1.rotate(degreesToRadians(45));
/* Concatenate the original matrix onto the rotated
matrix so we don't lose the original X and Y
coordinates and any other effects. */
m1.concat(img2.transform.matrix);
/* "Copy" the new matrix over the existing matrix. */
img2.transform.matrix = m1;
/* Set the appropriate Label text. */
lbl2.text = "img2.rotation = " + img2.rotation.toString() + deg;
}
private function img_rollOver(cTarget:UIComponent):void {
cTarget.toolTip = cTarget.name + ".rotation = " + cTarget.rotation.toString();
}
private function radiansToDegrees(radians:Number):Number {
var degrees:Number = radians * (180 / Math.PI);
return degrees;
}
private function degreesToRadians(degrees:Number):Number {
var radians:Number = degrees * (Math.PI / 180);
return radians;
}
]]>
</mx:Script>
<mx:Rotate id="rotate" angleFrom="0" angleTo="45" duration="1" />
<mx:ApplicationControlBar dock="true">
<mx:Label id="lbl1" />
<mx:Spacer width="50" />
<mx:Label id="lbl2" />
</mx:ApplicationControlBar>
<mx:Image id="img1"
source="http://www.helpexamples.com/flash/images/logo.png"
creationCompleteEffect="{rotate}"
effectEnd="img1_effectEnd();"
rollOver="img_rollOver(UIComponent(event.currentTarget));" />
<mx:Spacer width="50" />
<mx:Image id="img2"
source="http://www.helpexamples.com/flash/images/logo.png"
creationComplete="img2_creationComplete();"
rollOver="img_rollOver(UIComponent(event.currentTarget));" />
</mx:Application>
View source is enabled in the following example.
And just for giggles, here is a similar example which lets you rotate the image using a couple of Button controls. Note that the rotation is done around the center point of the image by calling the Matrix class’s translate() method to move the image before and after the rotation.
<?xml version="1.0" encoding="utf-8"?>
<!-- http://blog.flexexamples.com/2007/09/14/rotating-images-using-the-matrix-class/ -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white">
<mx:Script>
<![CDATA[
private function button_click(evt:Event):void {
var direction:int;
switch (evt.currentTarget) {
case degreesUp:
direction = +1;
break;
case degreesDown:
direction = -1;
break;
}
var radians:Number = degreesToRadians(direction);
var offsetWidth:Number = img.width / 2;
var offsetHeight:Number = img.height / 2;
var tempMatrix:Matrix = img.transform.matrix;
tempMatrix.translate(-offsetWidth, -offsetHeight);
tempMatrix.rotate(radians);
tempMatrix.translate(+offsetWidth, +offsetHeight);
img.transform.matrix = tempMatrix;
rotateDeg = img.rotation;
}
private function radiansToDegrees(radians:Number):Number {
var degrees:Number = radians * (180 / Math.PI);
return degrees;
}
private function degreesToRadians(degrees:Number):Number {
var radians:Number = degrees * (Math.PI / 180);
return radians;
}
]]>
</mx:Script>
<mx:Number id="rotateDeg">0</mx:Number>
<mx:NumberFormatter id="numberFormatter" precision="0" />
<mx:String id="deg">{String.fromCharCode(176)}</mx:String>
<mx:ApplicationControlBar dock="true">
<mx:Label text="rotation:" />
<mx:Button id="degreesUp"
label="+"
autoRepeat="true"
click="button_click(event);"
buttonDown="button_click(event);" />
<mx:Button id="degreesDown"
label="-"
autoRepeat="true"
click="button_click(event);"
buttonDown="button_click(event);" />
<mx:Spacer width="50" />
<mx:Label id="lbl"
text="{numberFormatter.format(rotateDeg)}{deg}" />
</mx:ApplicationControlBar>
<mx:VBox>
<mx:Image id="img"
source="http://www.helpexamples.com/flash/images/logo.png" />
</mx:VBox>
</mx:Application>
View source is enabled in the following example.





This line doesn’t work for me:
°
But this does:
{String.fromCharCode(176)}
Good example.
Flanture,
Thanks, good catch! Another case of me forgetting to web-friendly the MXML code after posting it in the Interwebs.
Example updated above and should hopefully work now. I’ll try and get View Source-able SWFs posted later this evening.
Peter
Hello I have Problem :(
I want to leave this image on the position. an image will to rotate automacally.
I see that mxml, why do you not use with ? I am ztying with problem of rotating image. :(
Thanks Joe Corner Reeve
This is fine
beautiful! thank you, thank you, searched entire web for this and this is the only working example in all of googleland. thanks!
c
If you examine the example carefully, it doesn’t rotate consistently around the exact center of the image. And then, if you go through an entire 360 degrees, the image position will be about 10 pixels or so below where it started.
Using absolute positioning, try this function below instead. You have to pass the original x and y of the image control, don’t use the .x or .y properties since they change when the image is transformed.
private function transformImage(img:Image, x:Number, y:Number, angle:Number):void { var offsetWidth:Number = img.contentWidth / 2 ; var offsetHeight:Number = img.contentHeight / 2 ; var sin=Math.sin(angle); var cos=Math.cos(angle); var tempMatrix:Matrix = new Matrix(); tempMatrix.a = cos; tempMatrix.b = -sin; tempMatrix.c = sin; tempMatrix.d = cos; tempMatrix.tx = x - cos * offsetWidth - sin * offsetHeight + offsetWidth; tempMatrix.ty = y + sin * offsetWidth - cos * offsetHeight + offsetHeight; img.transform.matrix = tempMatrix; }Is it okay to use this on my own site? I’m happy to link back to you from my new site which I hope to have running by the end of January. Happy New Year to you, I hope it’s a good one!
Man, I got worked trying to integrate this into my own application. If the the Image is not the only thing included in the VBox, this example no longer behaves as advertised. Seems that the matrix is relative to whatever container the Image resides in, not the Image itself. Just making sure this is clear to others who are still new to this stuff.
Can someone please explain to why the image needs to be in a VBox? This makes no sense to me.
private function transformImage(img:Image, x:Number, y:Number, angle:Number):void {
var offsetWidth:Number = img.contentWidth / 2 ;
var offsetHeight:Number = img.contentHeight / 2 ;
var sin=Math.sin(angle);
var cos=Math.cos(angle);
var tempMatrix:Matrix = new Matrix();
tempMatrix.a = cos;
tempMatrix.b = -sin;
tempMatrix.c = sin;
tempMatrix.d = cos;
tempMatrix.tx = x - cos * offsetWidth - sin * offsetHeight + offsetWidth;
tempMatrix.ty = y + sin * offsetWidth - cos * offsetHeight + offsetHeight;
img.transform.matrix = tempMatrix;