Basic Transform
任意の点を中心に拡大、縮小、回転.
四角形をクリックするとトランスフォームの基準点を変更.
/**
* Copyright imajuk ( http://wonderfl.net/user/imajuk )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/1G3c
*/
package
{
import flash.geom.Point;
import flash.events.Event;
import flash.display.Sprite;
/**
* 任意の点を中心に拡大、縮小、回転.
* 四角形をクリックするとトランスフォームの基準点を変更.
*/
[SWF(backgroundColor="#000000")]
public class Main extends Sprite
{
private var value:Number = 0;
public function Main()
{
stage.frameRate = 60;
var rect:Rect = addChild(new Rect()) as Rect;
rect.translate(stage.width * .5, stage.height * .5);
addEventListener(Event.ENTER_FRAME, function():void
{
value += .01;
var scale:Number = Math.sin(value);
var center:Point = rect.center;
//回転
DisplayObjectUtil.rotate(rect, center, MathUtil.degreesToRadians(value * 1000));
//拡大・縮小
DisplayObjectUtil.scale(rect, center, scale, scale);
/**
* 誤差補正
* Matrixによるトランスフォームはどうしても100分の1ピクセル単位の誤差が出てしまうためここで補正.
* もっといい方法はないだろうか?
*/
rect.revisePosition();
});
}
}
}
import flash.geom.Matrix;
import flash.display.DisplayObject;
import flash.geom.Point;
import flash.events.MouseEvent;
import flash.display.Graphics;
import flash.display.Sprite;
class Rect extends Sprite
{
private var size:Number = 150;
private var clickedLocal:Point = new Point(size * .5, size * .5);
private var clickedGlobal:Point = center;
public function get center():Point
{
return localToGlobal(clickedLocal);
}
private function getColor():Number
{
return Math.random() * 0xFFFFFF;
}
public function Rect()
{
draw(getColor());
addEventListener(MouseEvent.CLICK, clickHandler);
}
public function translate(tx:Number, ty:Number):void
{
x = tx;
y = ty;
clickedLocal.add(new Point(tx, ty));
clickedGlobal = center;
}
private function draw(color:Number):void
{
graphics.clear();
drawShape(size, color);
drawCenterPoint(clickedLocal, color);
}
private function drawShape(size:Number, color:uint):void
{
var g:Graphics = graphics;
g.lineStyle(1, color);
g.beginFill(color, .3);
g.drawRoundRectComplex(0, 0, size, size, 4, 4, 4, 4);
g.endFill();
}
private function drawCenterPoint(localPos:Point, color:uint):void
{
var markSize:int = 2;
var lx:Number = localPos.x;
var ly:Number = localPos.y;
var g:Graphics = graphics;
g.lineStyle(1, color);
g.moveTo(lx - markSize, ly - markSize);
g.lineTo(lx + markSize, ly + markSize);
g.moveTo(lx + markSize, ly - markSize);
g.lineTo(lx - markSize, ly + markSize);
}
public function revisePosition():void
{
var p1:Point = clickedGlobal;
var p2:Point = center;
var dx:Number = p1.x - p2.x;
var dy:Number = p1.y - p2.y;
x += dx;
y += dy;
}
private function clickHandler(event:MouseEvent):void
{
clickedLocal = new Point(event.localX, event.localY);
clickedGlobal = new Point(event.stageX, event.stageY);
draw(getColor());
}
}
class DisplayObjectUtil
{
/**
* 対象となるDisplayObjectを、任意の点を原点として回転させます.
* @param target 対象となるDisplayObject
* @param origin 回転の中心となるグローバル座標
* @param radians 新しい角度.これは絶対値です.
*/
public static function rotate(target:DisplayObject, origin:Point, radians:Number):void
{
var m:Matrix = target.transform.matrix;
var x:Number = origin.x;
var y:Number = origin.y;
m.concat(new Matrix(1, 0, 0, 1, -x, -y));
m.rotate(radians - MathUtil.degreesToRadians(target.rotation));
m.concat(new Matrix(1, 0, 0, 1, x, y));
target.transform.matrix = m;
}
/**
* 対象となるDisplayObjectを、任意の点を原点として拡大・縮小させます.
* @param target 対象となるDisplayObject
* @param origin 拡大・縮小の中心となるグローバル座標
* @param scaleX 新しいスケールX.これは絶対値です.
* @param scaleY 新しいスケールY.これは絶対値です.
*/
public static function scale(target:DisplayObject, origin:Point, scaleX:Number, scaleY:Number):void
{
var m:Matrix = target.transform.matrix;
var x:Number = origin.x;
var y:Number = origin.y;
m.concat(new Matrix(1, 0, 0, 1, -x, -y));
m.scale(1 / target.scaleX, 1 / target.scaleY);
m.scale(scaleX, scaleY);
m.concat(new Matrix(1, 0, 0, 1, x, y));
target.transform.matrix = m;
}
}
class MathUtil
{
private static const PI:Number = Math.PI;
/**
* 渡された任意の角度をラジアンに変換します.
*
* @param degrees ラジアンに変換したい角度を渡します.
* @return 角度からラジアンに変換された値を返します.
*/
public static function degreesToRadians(degrees:Number):Number
{
return degrees * PI / 180;
}
}