In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Flash Tip collection 10 : Rotating Around Point

...
@author YopSolo

The flash API do not provide a way to change the Pivot of a display object
but I found a class called MatrixTransformer in the fl.motion package that can allow to do it quickly
via the static method rotateAroundInternalPoint
documentation 
http://help.adobe.com/fr_FR/FlashPlatform/reference/actionscript/3/fl/motion/MatrixTransformer.html
the class can be found in flex sdk
Get Adobe Flash player
by YoupSolo 26 Jul 2015

    Talk

    NME at 30 Jul 2015 15:32
    I remember when I needed this years ago, and it wasn't in the doc. I had to roll my own, because I had to get it out there, but then this guy showed it to me on the flashcoders list after I sent the swf to the client. Wow, those were the days.*sigh*
    YoupSolo at 22 Aug 2015 00:47
    yep ^^ fortunatly new libs like Starling give us pivotX/pivotY with the v1 :)
    Embed
/**
 * Copyright YoupSolo ( http://wonderfl.net/user/YoupSolo )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/24VO
 */

package
{
    import flash.display.DisplayObjectContainer;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;   

    /**
     * ...
     * @author YopSolo
     *
     * The flash API do not provide a way to change the Pivot of a display object
     * but I found a class called MatrixTransformer in the fl.motion package that can allow to do it quickly
     * via the static method rotateAroundInternalPoint
     * documentation 
     * http://help.adobe.com/fr_FR/FlashPlatform/reference/actionscript/3/fl/motion/MatrixTransformer.html
     * the class can be found in flex sdk
     */
    public class Main extends Sprite
    {
        private var _shapes:Vector.<Shape>;       

        public function Main()
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }       

        private function init(e:Event = null):void
        {

            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point           

            var bg:Shape = new Shape();
            bg.graphics.beginFill(0x333333);
            bg.graphics.drawRect(0, 0, 465, 465);
            bg.cacheAsBitmap = true;
            addChild(bg);            

            // add custom menu
            new CustomMenu(this);
            
            run();
        }

        private function run():void
        {
            buildTextField(this, 'TIP 10 : Rotation around a point', 2, 2);
            _shapes = new Vector.<Shape>();
            
            var shape:Shape = new Shape();
            for (var i:int = 0; i < 5; i++)
            {
                shape = new Shape();
                shape.graphics.beginFill(0xFFFFFF * Math.random(), 1);
                shape.graphics.drawRect(0, 0, 200, 200);
                shape.graphics.endFill();

                shape.x = 233 - 100;
                shape.y = 233 - 100;
                _shapes.push(addChild(shape));
            }
            addEventListener(Event.ENTER_FRAME, _oef);
        }

        private function _oef(e:Event):void
        {
            var sh:Shape;
            for (var i:int = 0; i < _shapes.length; i++)
            {
                sh = _shapes[i];
                var mtx:Matrix = sh.transform.matrix.clone();
                MatrixTransformer.rotateAroundInternalPoint(mtx, 100, 100, .5 + i/2 ); // rotate around the center point of the shape => 200 200 rect
                sh.transform.matrix = mtx;
            }
        }

        private function buildTextField(doc:DisplayObjectContainer, txt:String, x:int = 0, y:int = 0):TextField
        {
            var fmt:TextFormat = new TextFormat;
            fmt.color = 0xFFFFFF;
            fmt.font = 'Arial'; //(new FONT_HARMONY() as Font).fontName;
            fmt.size = 11; // 8;
            var tf:TextField = new TextField;
            tf.autoSize = TextFieldAutoSize.LEFT;
            tf.opaqueBackground = 0x0; // opaque background allow a perfect font rendering even in StageQuality.LOW mode
            tf.selectable = false;
            //tf.embedFonts = true;
            tf.defaultTextFormat = fmt;
            tf.text = txt;
            tf.x = x;
            tf.y = y;
            doc.addChild(tf);

            return tf;
        }
    }
}

import flash.display.Sprite;
import flash.events.ContextMenuEvent;
import flash.geom.*;
import flash.net.navigateToURL;
import flash.net.URLRequest;
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;

class CustomMenu
{
    private const NAME:String = "Flash Tips Collection : 'Rotation around Point'";
    public function CustomMenu(ref:Sprite):void
    {
        var appContextMenu:ContextMenu = new ContextMenu;
        appContextMenu.hideBuiltInItems();
        var cmi:ContextMenuItem = new ContextMenuItem(NAME);
        var credits:ContextMenuItem = new ContextMenuItem("by YopSolo");
        appContextMenu.customItems.push(cmi);
        appContextMenu.customItems.push(credits);

        cmi.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, _onClickCollection);
        credits.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, _onClickCredits);

        ref.contextMenu = appContextMenu;
    }

    private function _onClickCollection(e:ContextMenuEvent):void
    {
        navigateToURL(new URLRequest('http://www.yopsolo.fr/wp/2012/01/14/flash-tips-collection/'), '_blank');
    }

    private function _onClickCredits(e:ContextMenuEvent):void
    {
        navigateToURL(new URLRequest('http://www.yopsolo.fr'), '_blank');
    }
}

// source flex sdk
// http://help.adobe.com/fr_FR/FlashPlatform/reference/actionscript/3/fl/motion/MatrixTransformer.html
/**

 * The MatrixTransformer class contains methods for modifying individual properties of a transformation matrix:

 * horizontal and vertical scale, horizontal and vertical skew, and rotation.

 * This class also has methods for rotating around a given transformation point rather than the typical (0, 0) point.

 * @playerversion Flash 9.0.28.0

 * @langversion 3.0

 * @keyword MatrixTransformer, Copy Motion as ActionScript

 * @see ../../motionXSD.html Motion XML Elements

 * @see flash.geom

 */





class MatrixTransformer

{

    /**

     * Calculates the horizontal scale present in a matrix.

     *

     * @param m A Matrix instance.

     *

     * @return The horizontal scale.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function getScaleX(m:Matrix):Number

    {

        return Math.sqrt(m.a * m.a + m.b * m.b);

    }

    

    /**

     * Changes the horizontal scale in a matrix.

     *

     * @param m A Matrix instance to be modified.

     *

     * @param scaleX The new horizontal scale.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function setScaleX(m:Matrix, scaleX:Number):void

    {

        var oldValue:Number = getScaleX(m);

        // avoid division by zero 

        if (oldValue)

        {

            var ratio:Number = scaleX / oldValue;

            m.a *= ratio;

            m.b *= ratio;

        }

        else

        {

            var skewYRad:Number = getSkewYRadians(m);

            m.a = Math.cos(skewYRad) * scaleX;

            m.b = Math.sin(skewYRad) * scaleX;

        }

    }

    

    /**

     * Calculates the vertical scale present in a matrix.

     *

     * @param m A Matrix instance.

     *

     * @return The vertical scale.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function getScaleY(m:Matrix):Number

    {

        return Math.sqrt(m.c * m.c + m.d * m.d);

    }

    

    /**

     * Changes the vertical scale in a matrix.

     *

     * @param m A Matrix instance to be modified.

     *

     * @param scaleY The new vertical scale.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function setScaleY(m:Matrix, scaleY:Number):void

    {

        var oldValue:Number = getScaleY(m);

        // avoid division by zero 

        if (oldValue)

        {

            var ratio:Number = scaleY / oldValue;

            m.c *= ratio;

            m.d *= ratio;

        }

        else

        {

            var skewXRad:Number = getSkewXRadians(m);

            m.c = -Math.sin(skewXRad) * scaleY;

            m.d = Math.cos(skewXRad) * scaleY;

        }

    }

    

    /**

     * Calculates the angle of horizontal skew present in a matrix, in radians.

     *

     * @param m A Matrix instance.

     *

     * @return The angle of horizontal skew, in radians.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function getSkewXRadians(m:Matrix):Number

    {

        return Math.atan2(-m.c, m.d);

    }

    

    /**

     * Changes the horizontal skew in a matrix.

     *

     * @param m A Matrix instance to be modified.

     *

     * @param skewX The new horizontal skew, in radians.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function setSkewXRadians(m:Matrix, skewX:Number):void

    {

        var scaleY:Number = getScaleY(m);

        m.c = -scaleY * Math.sin(skewX);

        m.d = scaleY * Math.cos(skewX);

    }

    

    /**

     * Calculates the angle of vertical skew present in a matrix, in radians.

     *

     * @param m A Matrix instance.

     *

     * @return The angle of vertical skew, in radians.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function getSkewYRadians(m:Matrix):Number

    {

        return Math.atan2(m.b, m.a);

    }

    

    /**

     * Changes the vertical skew in a matrix.

     *

     * @param m A Matrix instance to be modified.

     *

     * @param skewY The new vertical skew, in radians.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function setSkewYRadians(m:Matrix, skewY:Number):void

    {

        var scaleX:Number = getScaleX(m);

        m.a = scaleX * Math.cos(skewY);

        m.b = scaleX * Math.sin(skewY);

    }

    

    /**

     * Calculates the angle of horizontal skew present in a matrix, in degrees.

     *

     * @param m A Matrix instance.

     *

     * @return The angle of horizontal skew, in degrees.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function getSkewX(m:Matrix):Number

    {

        return Math.atan2(-m.c, m.d) * (180 / Math.PI);

    }

    

    /**

     * Changes the horizontal skew in a matrix.

     *

     * @param m A Matrix instance to be modified.

     *

     * @param skewX The new horizontal skew, in degrees.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function setSkewX(m:Matrix, skewX:Number):void

    {

        setSkewXRadians(m, skewX * (Math.PI / 180));

    }

    

    /**

     * Calculates the angle of vertical skew present in a matrix, in degrees.

     *

     * @param m A Matrix instance.

     *

     * @return The angle of vertical skew, in degrees.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function getSkewY(m:Matrix):Number

    {

        return Math.atan2(m.b, m.a) * (180 / Math.PI);

    }

    

    /**

     * Changes the vertical skew in a matrix.

     *

     * @param m A Matrix instance to be modified.

     *

     * @param skewX The new vertical skew, in degrees.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function setSkewY(m:Matrix, skewY:Number):void

    {

        setSkewYRadians(m, skewY * (Math.PI / 180));

    }

    

    /**

     * Calculates the angle of rotation present in a matrix, in radians.

     * If the horizontal and vertical skews are not equal,

     * the vertical skew value is used.

     *

     * @param m A Matrix instance.

     *

     * @return The angle of rotation, in radians.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function getRotationRadians(m:Matrix):Number

    {

        return getSkewYRadians(m);

    }

    

    /**

     * Changes the angle of rotation in a matrix.

     * If the horizontal and vertical skews are not equal,

     * the vertical skew is set to the rotation value

     * and the horizontal skew is increased by the difference between the

     * old rotation and the new rotation.

     * This matches the rotation behavior in Flash Player.

     *

     * @param m A Matrix instance.

     *

     * @param rotation The angle of rotation, in radians.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function setRotationRadians(m:Matrix, rotation:Number):void

    {

        var oldRotation:Number = getRotationRadians(m);

        var oldSkewX:Number = getSkewXRadians(m);

        setSkewXRadians(m, oldSkewX + rotation - oldRotation);

        setSkewYRadians(m, rotation);

    }

    

    /**

     * Calculates the angle of rotation present in a matrix, in degrees.

     * If the horizontal and vertical skews are not equal,

     * the vertical skew value is used.

     * This matches the rotation behavior in Flash Player.

     *

     * @param m A Matrix instance.

     *

     * @return The angle of rotation, in degrees.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function getRotation(m:Matrix):Number

    {

        return getRotationRadians(m) * (180 / Math.PI);

    }

    

    /**

     * Changes the angle of rotation in a matrix.

     * If the horizontal and vertical skews are not equal,

     * the vertical skew is set to the rotation value

     * and the horizontal skew is increased by the difference between the

     * old rotation and the new rotation.

     * This matches the rotation behavior in Flash Player.

     *

     * @param m A Matrix instance.

     *

     * @param rotation The angle of rotation, in degrees.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function setRotation(m:Matrix, rotation:Number):void

    {

        setRotationRadians(m, rotation * (Math.PI / 180));

    }

    

    /**

     * Rotates a matrix about a point defined inside the matrix's transformation space.

     * This can be used to rotate a movie clip around a transformation point inside itself.

     *

     * @param m A Matrix instance.

     *

     * @param x The x coordinate of the point.

     *

     * @param y The y coordinate of the point.

     *

     * @param angleDegrees The angle of rotation in degrees.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function rotateAroundInternalPoint(m:Matrix, x:Number, y:Number, angleDegrees:Number):void

    {

        var point:Point = new Point(x, y);

        point = m.transformPoint(point);

        m.tx -= point.x;

        m.ty -= point.y;

        m.rotate(angleDegrees * (Math.PI / 180));

        m.tx += point.x;

        m.ty += point.y;

    }

    

    /**

     * Rotates a matrix about a point defined outside the matrix's transformation space.

     * This can be used to rotate a movie clip around a transformation point in its parent.

     *

     * @param m A Matrix instance.

     *

     * @param x The x coordinate of the point.

     *

     * @param y The y coordinate of the point.

     *

     * @param angleDegrees The angle of rotation in degrees.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function rotateAroundExternalPoint(m:Matrix, x:Number, y:Number, angleDegrees:Number):void

    {

        m.tx -= x;

        m.ty -= y;

        m.rotate(angleDegrees * (Math.PI / 180));

        m.tx += x;

        m.ty += y;

    }

    

    /**

     * Moves a matrix as necessary to align an internal point with an external point.

     * This can be used to match a point in a transformed movie clip with one in its parent.

     *

     * @param m A Matrix instance.

     *

     * @param internalPoint A Point instance defining a position within the matrix's transformation space.

     *

     * @param externalPoint A Point instance defining a reference position outside the matrix's transformation space.

     * @playerversion Flash 9.0.28.0

     * @langversion 3.0

     * @keyword Matrix, Copy Motion as ActionScript

     * @see flash.geom.Matrix

     */

    public static function matchInternalPointWithExternal(m:Matrix, internalPoint:Point, externalPoint:Point):void

    {

        var internalPointTransformed:Point = m.transformPoint(internalPoint);

        var dx:Number = externalPoint.x - internalPointTransformed.x;

        var dy:Number = externalPoint.y - internalPointTransformed.y;

        m.tx += dx;

        m.ty += dy;

    }



}