Saturnboy
 9.19

Many ways to do the same thing…but which is right? It’s an issue developers face every single day.

Here’s one of those issues that I faced this past week: rotating an object in Flex. I was playing with the camera in Flex Mobile, and I quickly learned that it is landscape only even if the device is being held in portrait. Really, Adobe?

“…a Video object attached to the camera will only show upright video in a landscape-aspect orientation. Thus, mobile apps should use a landscape orientation when displaying video and should not auto-rotate.”
     – official Adobe docs for flash.media.Camera

Sad but true. So, if you wanted to build a video chat app and use the front camera you either always hold the iPhone in landscape or you hold it portrait and rotate the video in code. (Why did I say iPhone?…Alas, Flex Mobile does not provide front camera support for Android…period…none!)

Option 1: rotation Attribute

The first thing to try is to rotate the easy way, like this:

camera.rotation = 90;

Using actionscript, I just set the rotation to 90°. Of course, this rotates about (0,0), the upper left corner in Flex, and not what we need.

Option 2: rotation, Plus transformX and transformY

To rotate an object about its center, you can set transformX and transformY (and transformZ too), like this:

<s:Button id="btn" label="My Button"
    rotation="90"
    transformX="{btn.width * 0.5}"
    transformY="{btn2.height * 0.5}" />

Using MXML, I set rotation to 90°, plus transformX and transformY to half the width and height of the object (in this case, a button). By moving the rotation point from the top left to the center of the button, I get what I want: an object rotating about its center. [I had forgotten how this works...thanks go to Bindu for reminding me!]

Option 3: Matrix Rotation

Option #2 works because every component in Flex has a full affine transformation matrix behind it (as of Flash Player v9, I think, but only exposed to MXML in Flex 4). In MXML, when you set attributes like rotation, transformX, and transformY, you are just setting the underlying transformation matrix.

You can also set the matrix directly, like this:

var mat:Matrix = new Matrix();
mat.translate(-W/2, -H/2);
mat.rotate(Math.PI/2);
mat.translate(+W/2, +H/2);
mat.concat(myObj.transform.matrix);
myObj.transform.matrix = mat;

To get a rotation about the center of our object, we first translate it, then rotate, then translate it back. Note the concat() operation, which just “adds” the current matrix to our new rotation matrix, and thus preserves any previous transforms (maybe our object had scaleX or scaleY applied).

Option 4: Rotate Animation

Lastly, if we want to watch the rotation happen, we can use a Rotate animation, like this:

var rot:Rotate = new Rotate();
rot.angleBy = 90;
rot.duration = 1000;
rot.autoCenterTransform = true;
rot.target = myObj;
rot.play();

Here we just instantiate a new spark Rotate effect, set its various properties, and start it with a call to play(). The key property to force rotation about the center is autoCenterTransform, just set it to true.

Conclusion

When I need total control, I find myself doing the full matrix solution. Otherwise for anything simple, the MXML attributes are best.

Here’s an example project showing all options (view source enabled):

Flash is required. Get it here!
Files

© 2014 saturnboy.com