02-08-2011 06:47 PM
Hi guys,
I tried this for some hours today and am now desperate enough to ask...
In a project I need to rotate an image (not animated) around it's center. According to the web there are several Actionscript3-ways, but not a single one worked for me.
Here's my basic code:
var cInner:Image = new Image;
cInner.setImage('inner.png');
cInner.setSize(470,470);
cInner.setPosition(50,50);
cont3Container.addChild(cInner); // cont3Container is used for layout purposes
Try I
cInner.rotationZ = 10;
If any of the parameters rotationX/Y/Z are set, the image disappears magically - altough the AIR debugger still shows cInner's correct position and size.
Try II
cInner.rotation = 10;
It works "somehow", but deforms my image (skew) and moves it to other (x,y) coordinates.
Try III
Using the method I found here (creating a seperate transition matrix). I get the same result as in Try II: a deformed image.
Try IV
A friend of mine told me it would be wise to wrap my image in a new MovieClip and rotate the whole clip ("the 'ol Flash way of doing things"). But I failed creating this special kind of container:
mov = new MovieClip(); mov.width = 470; mov.height = 470; mov.x = 50; mov.y = 50; addChild(mov); // or added to cont3Container - makes no difference /* ... */ mov.addChild(cInner);
It does not show up - AIR debugger tells me, that mov's width is 0 (zero).
I think I need an expert now. Who can help? Ugly workarounds are highly appreciated. ![]()
Solved! Go to Solution.
02-08-2011 07:15 PM
Odd. Have you tried adding the image to a Sprite and then try rotating the Sprite?
02-08-2011 07:32 PM
Sprites behave the same way:
var spr:Sprite = new Sprite(); spr.width = 470; spr.height = 470; spr.x = 450; spr.y = 150; spr.addChild(cInner); addChild(spr); trace(spr.width);
I suppose trace should return 470. Insted it returns 0 and I have no clue why...
02-08-2011 07:39 PM
@biggerCC: the reason for the invalid width read out is because that read out is before the image is actually loaded. it takes time for the Image object to load the image from the file system. the code you have runs "instantly" so it prints it out to you before the load is complete. you have two options, to get a correct read out, you have to either add an event listener and listen for the Event.COMPLETE event on the image and then retreieve and the widths and heights or you can use an embedded image and it'll work for you without needing an event listener because the image is "preloaded" into your application.
as for the rotation, i've never tried but seems really interesting. im gonna have to try it out. good luck!
02-08-2011 07:42 PM - edited 02-08-2011 07:42 PM
Could it be that you have to embed the image similar to rotating labels?
EDIT: JRab beat me to it lol
02-08-2011 08:19 PM
No, fonts are different in terms of rotation. There is absolutely no reason why an image cannot be rotated once it has been loaded.
02-08-2011 08:30 PM - edited 02-08-2011 08:31 PM
hey biggerCC,
i managed to get a circular object rotated as expected. it takes some doing though. the concept of rotation is a little different because i think AS3 takes the point of origin of a sprite and rotates it there, however we wish it would rotate based on a midpoint.
the solution to that is to use a matrix as you had previously discovered. i found the following website and ran through its code and pumped out my own based on it. so all credit goes to this website:
http://www.8bitrocket.com/2007/10/30/Actionscript-
as for the code, here it is:
ImageTest.as:
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import qnx.ui.buttons.LabelButton;
import qnx.ui.display.Image;
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#BBBBBB")]
public class ImageTest extends Sprite
{
[Embed(source="images/BallNumber.png")]
private var myEmbeddedImage:Class;
private var myBitmap:Bitmap;
private var myImage:Image;
private var myBtn:LabelButton;
private var rotationObjectData:Object;
public function ImageTest()
{
super();
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
/**
* Setup your bitmap image
**/
myBitmap = new myEmbeddedImage();
/**
* setup your rotation object data
* i found its best to keep it all organized
* to one object just as the original website had it
**/
rotationObjectData = new Object();
/* setup the orignal data to we are working with by grabbing the bitmap data */
rotationObjectData.sourceBitmapData = myBitmap.bitmapData;
/* set up the bitmap data that we are going to modify constantly keeping the original intact */
rotationObjectData.displayBitmapData = new BitmapData(myBitmap.width, myBitmap.height, true, 0xFFFFFFFF);
/* we copy the original data to the modifiable data */
rotationObjectData.displayBitmapData.copyPixels(ro tationObjectData.sourceBitmapData, new Rectangle(0,0,myBitmap.width, myBitmap.height), new Point(0,0));
rotationObjectData.rotation = 0;
/**
* Set up your image object
**/
myImage = new Image();
/* set the original image the user sees to the source bitmap data */
myImage.setImage(rotationObjectData.sourceBitmapDa ta);
myImage.setPosition(100,100);
addChild(myImage);
/**
* setup your button to rotate with
**/
myBtn = new LabelButton();
myBtn.label = "Rotate";
myBtn.setSize(150,52);
myBtn.setPosition(700,300);
myBtn.addEventListener(MouseEvent.CLICK, onClick);
addChild(myBtn);
}
private function onClick(e:MouseEvent):void
{
/**
* this is where it gets hairy
**/
/* set the rotation increase from its previous number */
rotationObjectData.rotation += 18;
var degrees:int = rotationObjectData.rotation;
/* the rotation value is in radians so we need to convert our degrees to radians */
var angle_in_radians:Number = Math.PI * 2 * (degrees / 360);
/**
* Setup the rotation matrix
**/
var rotationMatrix:Matrix = new Matrix();
/* all this transform the rotation matrix so we can have our bitmap data transformed later */
rotationMatrix.translate(-(myBitmap.width / 2),-(myBitmap.height / 2));
rotationMatrix.rotate(angle_in_radians);
rotationMatrix.translate((myBitmap.width / 2),(myBitmap.height / 2));
/**
* using the rotation matrix, we create our rotated bitmap (finally)
**/
var matrixImage:BitmapData = new BitmapData(myBitmap.width, myBitmap.width, true, 0x00000000);
/* based on the original image, we create the new rotated image using its bitmap data */
matrixImage.draw(rotationObjectData.sourceBitmapDa ta, rotationMatrix);
/* we set our modifiable displayBitmapData property to the new image */
rotationObjectData.displayBitmapData = matrixImage;
/**
* Set the new image after rotation
**/
myImage.setImage(rotationObjectData.displayBitmapD ata);
}
}
}
I've included comments as much as i could to explain it. if you need further explanation, please let me know. i've also attached the image i used for the testing. also you may notice i used an embedded image. it makes things a whole lot easier and its quick (no need to load from the file system). you can changet he embed path to anything you want without changing the rest of the code and the same rotation will apply.
hope that helps. was pretty fun. good luck!
@jffurian: sorry ![]()
02-08-2011 08:35 PM
Problem is likely that you have to offset the child (your image) within the container to get the rotation you want.
var spr:Sprite = new Sprite();
//this will make sure that spr 0,0 coords are the centre of your img
cInner.x = -( cInner.width / 2 );
cInner.y = -( cInner.height / 2 );
// we have to add have the width and height again to make it look like its in the same spot
spr.x = 450 + (cInner.width/2);
spr.y = 150 + (cInner.height/2);
spr.addChild(cInner);
addChild(spr);
// then!
spr.rotation += 45; // or however much you want
HTH
02-08-2011 11:40 PM
Just happens I encountered this issue today and did a lot of the same research. I was lucky enough to stumble over the Rotator class, which totally solved my problem, is small and simple, and even works nicely with Tweener.
The basic problem seems to be that image rotation works on a "registration point" at the upper left corner of the image. This means it will rotate, but not around its own centre, so it can easily "vanish" as you've seen.
02-08-2011 11:46 PM - edited 02-08-2011 11:47 PM
@peter: does seem pretty simple. i gotta admit i spent a good five minutes playing around with the demo on that page haha. i have such an addictive personality ![]()