Rotating images using the Matrix class
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.
Peter deHaan
Peter deHaan currently works for Adobe on the Flex SDK QA team. While not working on Flex, Flash, and ColdFusion applications, Peter enjoys making up bios and writing in 3rd person. Peter's rarely updated blog can be found at blogs.adobe.com/pdehaan/, actionscriptexamples.com, airexamples.com, and coldfusionexamples.com.
-
Add Widgets (Content Sidebar)
This is your Content Sidebar. Edit this content that appears here in the widgets panel by adding or removing widgets in the Content Sidebar area.
23 Responses to Rotating images using the Matrix class
Leave a Reply Cancel reply
-
Categories
- Accordion
- AccordionHeader
- ActionScript
- AddChild
- AdvancedDataGrid
- Alert
- alpha
- Animate
- AnimateProperties
- Application
- Application (Spark)
- ArrayCollection
- BarChart
- baseColor
- beta
- beta1
- beta2
- Bitmap
- Bitmap/BitmapData
- BitmapData
- BitmapFill
- BitmapFill (Spark)
- BitmapGraphic
- BitmapImage
- BitmapImage (Spark)
- BitmapImageResizeMode
- Border (Spark)
- BorderContainer (Spark)
- Box
- BuildInfo
- Button
- Button (Spark)
- ButtonBar
- ButtonBar (Spark)
- ByteArray
- Camera
- Charting
- CheckBox
- CheckBox (Spark)
- ClassFactory
- CollectionEvent
- Color
- ColorPicker
- ColorUtil
- ComboBox
- ComboBoxArrowSkin
- Compiler
- Component
- Component (Spark)
- Configuration
- Container
- ContextMenu
- ContextMenuEvent
- ContextMenuItem
- CSSCondition
- CSSSelector
- CSSStyleDeclaration
- CurrencyFormatter
- CursorManager
- Data Binding
- DataGrid
- DataGrid (Spark)
- DataGridColumn
- Date
- DateBase
- DateChooser
- DateField
- DateFormatter
- Debugging
- DefaultComplexItemRenderer
- DefaultTileListEffect
- DropDownList
- DropDownList (Spark)
- DropDownListButtonSkin
- DropDownListSkin
- DropShadowFilter
- E4X
- Effects
- Ellipse
- EmailValidator
- Embed
- Event
- Fade
- FileFilter
- FileReference
- fill
- Filters
- Flash
- Flash Integration
- FlashVars
- Flex 3 SDK
- Flex Builder
- Flex Builder 3
- Flex SDK
- Flex4
- FLVPlayback
- FocusManager
- FontLookup
- Fonts
- Form
- Form (Spark)
- FormHeading (Spark)
- FormItem
- FormItem (Spark)
- Forms
- FTETextField (Spark)
- FullScreen
- FullScreenEvent
- FxAnimateColor
- FxButtonBar
- FxCheckBox
- FXG
- FxHScrollBar
- FxHSlider
- FxList
- FxNumericStepper
- FxRadioButton
- FxRotate3D
- FxScroller
- FxTextArea
- FxTextInput
- FxToggleButton
- FxVScrollBar
- FxVSlider
- getStyleDeclaration()
- GradientEntry
- Graphic (Spark)
- HBox
- HDividedBox
- HGroup (Spark)
- HorizontalLayout
- HorizontalList
- HSBColor (Spark)
- HScrollBar (Spark)
- HSlider
- HSlider (Spark)
- HTML template
- ID3Info
- Image
- Image (Spark)
- ImageSnapshot
- itemRenderer
- JointStyle
- Label
- Label (Spark)
- Legend
- LegendItem
- LigatureLevel
- Line
- LinearGradientStroke
- LineScaleMode
- LinkBar
- LinkButton
- List
- List (Spark)
- Menu
- MenuBar
- Metadata
- MetadataEvent
- Model
- Mouse
- MouseCursor
- MouseEvent
- Move
- Namespace
- NavigatorContent (Spark)
- needsSWF
- NetConnection
- NetStream
- Nightly Builds
- NumberBaseRoundType
- NumberFormatter
- NumberValidator
- NumericCompare
- NumericStepper
- NumericStepper (Spark)
- ObjectProxy
- ObjectUtil
- paddingLeft
- paddingRight
- Panel
- Panel (Spark)
- Parallel
- Path
- PieChart
- PieSeries
- PieSeriesItem
- PopUpAnchor (Spark)
- PopUpButton
- PopUpManager
- ProgrammaticSkin
- ProgressBar
- PropertyChangeEvent
- QName
- RadialGradient
- RadioButton
- RadioButton (Spark)
- RadioButtonGroup
- RadioButtonGroup (Spark)
- Rect
- RegExp
- Regular Expressions
- Repeater
- RichEditableText
- RichText
- RichText (Spark)
- RichTextEditor
- Rotate
- Rotate3D (Spark)
- Scroller (Spark)
- Sequence
- setStyle()
- SimpleText
- SimpleText (Spark)
- skinClass
- Slider
- SliderEvent
- SolidColor
- SolidColorStroke
- Sort
- SortField
- Sound
- SoundEffect
- Spinner (Spark)
- SpriteVisualElement (Spark)
- StageDisplayState
- States
- StringUtil
- StringValidator
- StyleManager
- Styles
- SWFLoader
- SWFObject
- System
- SystemManager
- TabBar
- TabBar (Spark)
- TabNavigator
- TabStopFormat
- Text
- Text Layout Framework (TLF)
- TextArea
- TextArea (Spark)
- TextBox
- TextConverter
- TextEvent
- TextFlow
- TextFlowUtil
- TextFormat
- TextGraphic
- TextInput
- TextInput (Spark)
- TextLayoutFormat
- TextView
- Themes
- TileLayout
- TileList
- TileOrientation
- Timer
- TitleWindow
- TitleWindow (Spark)
- TLF
- ToggleButton (Spark)
- ToggleButtonBar
- ToolTip
- Transition
- Tree
- TruncationOptions
- UIComponent
- UIFTETextField
- Updater
- URLLoader
- URLRequest
- URLUtil
- URLVariables
- ValidationResultEvent
- Validator
- Validators
- VBox
- VDividedBox
- Vector
- VerticalLayout
- VerticalLayout (Spark)
- VGroup (Spark)
- Video
- VideoDisplay
- VideoElement
- VideoElement (Spark)
- VideoEvent
- VideoPlayer (Spark)
- VideoPlayerScrubBar
- ViewStack
- VScrollBar (Spark)
- VSlider
- VSlider (Spark)
- XML
- XMLList
- XMLListCollection
- ZipCodeValidator
- ZipCodeValidatorDomainType
- Zoom
-
Articles
- December 2010
- November 2010
- October 2010
- September 2010
- August 2010
- July 2010
- June 2010
- May 2010
- April 2010
- March 2010
- February 2010
- January 2010
- December 2009
- November 2009
- October 2009
- September 2009
- August 2009
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
-
Meta


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;
Im losing my head here…
I’m trying to adapt this sample using slider insted button but it just won’t work. My code:
<code>
private function rotateImage(evt:SliderEvent):void {
evt.preventDefault();
var tar:Slider = Slider(evt.currentTarget);
var direction:int;
direction = tar.value;
var radians:Number = degreesToRadians(direction);
var offsetWidth:Number = abc.width / 2;
var offsetHeight:Number = abc.height / 2;
var tempMatrix:Matrix = abc.transform.matrix;
tempMatrix.translate(-offsetWidth, -offsetHeight);
tempMatrix.rotate(radians);
tempMatrix.translate(+offsetWidth, +offsetHeight);
abc.transform.matrix = tempMatrix;
cmtTxt.text = “Rotating image…” + direction;
}
</code>
I have the radiansToDegrees and degreesToRadians functions. The thing is, when I use this code, the X, Y, scaleX and scaleY get all mess and the image jumps from one side to the other. By the way, image its inside a canvas and yes, I am accessing the image.
Thanks!
Got a solution for my problem from Joel’s blog:
http://www.joelconnett.com/flex-rotation-around-a-point-using-a-matrix.html
Works like a charm!
Thanks :)
i have a problem with big images, when i rotate the image this get over other components like application control bar, there’s some way to resolve this issue? Cheers
I too have this issue .. have u got solution for this?.. if any body has solution for this please share with me..
What if y want a Y ax rotation ?
What the matrix will be ?
Regards
Aren’t there any developers out there who know how to spell and use good grammar? What is with you people?
Many of us are from non-english-speaking countries (and I’m not even sure what last sentence is correct…). Anyway… the thing is, nowadays, English is the unviversal language, and web try to adjust to it as good as we can, but it’s not easy, specially when the conversation is about technologies. Not my case, but there are a lot of fully qualified Flex developer in India, for example.
I don’t think that’s something to be sorry for… good grammar or bad grammar, the important thing is to give something back to the community that always helps us.
I have created a fully functional transform tool or object handler in as3 with the help of the matrix transform. Have a look http://talkxe.com/?p=63
Here is the code you need to rotate the item when it is not at the origin. The inverted matrix is to get to the local coordinates of the item, the offsets are to rotate around the middle, and then the items initial transform is concatenated to get back to the global coordinates. I wasn’t totally brushed up on my linear algebra and it sounds like this can save everyone some time.
The radians variable is the change in rotation to apply.
And how can I scale Image from center after I rotated it?
Hello,
i am trying to rotate my image which is a child of my view panel.
I wrote something like that :
var rotate:mx.effects.Rotate = new mx.effects.Rotate();
//var iTmp:Image = new Image();
//iTmp = viewerPanel.getChildAt(0) as Image;
rotate.target= viewerPanel.getChildAt(0);
rotate.angleFrom=viewerPanel.getChildAt(0).rotation;
rotate.angleTo=viewerPanel.getChildAt(0).rotation – 90;
rotate.duration=1000;
rotate.originX=viewerPanel.getChildAt(0).width/2;
rotate.originY=viewerPanel.getChildAt(0).height/2;
rotate.play();
it rotates the panel from top left.
then i wrote something like that :
var iTmp:Image = new Image();
iTmp = viewerPanel.getChildAt(0) as Image;
var q:Number = 90 * Math.PI / 180 // 30 degrees in radians
var m:Matrix = new Matrix();
var centerX:Number = iTmp.width / 2;
var centerY:Number = iTmp.height /2;
m.translate(-1 * centerX, -1 * centerY);
m.rotate(q);
viewerPanel.removeChildAt(0);
viewerPanel.addChild(iTmp);
and this made the same thing.
So How can i rotate an image which is added to a panel as a child ?
Thank you.
How do i set the duration for the rotation of a matrix object.
I cant seem to find someMatrix.rotate.duration or someMatrix.duration…
Hi, I’m using the above code to rotate and zoom images (SWF images). Currently I’m facing with a problem, where some of the SWF graphics are rotating and zooming perfectly, but there are some image, where this is not working. Graphics are jumping out of screen without controll. The only difference between the good and bad swf objects is the filetype. 7.0 is good others are not so :o( . Tried to convert objects to 7.0 but this is not working also. Have You ever seen this type of problem? Where can I find any solution for it? Any suggestion, what could be wrong? Many thanks in advance, Zsolt