...
@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
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*
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;
}
}