/* マトリックスを使って台形な変形 4点のポイントを用意して、その位置を元に変形。 台形といっても三角形が2つ合体させてます。 だらだら長いソースになってしまったけど、 _draw _getTransformMatrix の部分が重要なんで、他は無視無視無視無視無視無視無視無視!! */ package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.events.MouseEvent; import flash.geom.Matrix; import flash.geom.Point; import net.hires.debug.Stats; [SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "0x000000")] public class Teraco23_Matrix2 extends Sprite { private var _container:Sprite; private var _canvas:Sprite; private var _bmd:BitmapData; private var _stageW:Number = 465; private var _stageH:Number = 465; private var _cP0:CirclePoint; private var _cP1:CirclePoint; private var _cP2:CirclePoint; private var _cP3:CirclePoint; public function Teraco23_Matrix2() { //テスト用のBitmapData取得(重要じゃないので無視無視) _bmd = Bitmap(new TestImage()).bitmapData; //キャンバスを用意してコンテナに入れる(重要じゃないので無視無視) _canvas = new Sprite(); _container = new Sprite(); _container.addChild(_canvas); addChild(_container); _container.x = (_stageW - _bmd.width)/2; _container.y = (_stageH - _bmd.height)/2; //画像の大きさに合わせ、3点のポイントを配置(左上、右上、左下の3点) //CirclePointのコンストラクタの中で初期状態のポイント位置を保持してます。(initPoint) //その初期ポイントと、マウスドラッグで移動したポイントを比較してるのが、_drawの中。 _cP0 = new CirclePoint(0,0); _cP1 = new CirclePoint(_bmd.width,0); _cP2 = new CirclePoint(0,_bmd.height); _cP3 = new CirclePoint(_bmd.width,_bmd.height); _container.addChild(_cP0); _container.addChild(_cP1); _container.addChild(_cP2); _container.addChild(_cP3); //ポイントのドラッグとかの設定 //※ドラッグした時に_drawを呼び出してます。 _cP0.addEventListener(MouseEvent.MOUSE_DOWN , _cPMouseDownHandler ); _cP1.addEventListener(MouseEvent.MOUSE_DOWN , _cPMouseDownHandler ); _cP2.addEventListener(MouseEvent.MOUSE_DOWN , _cPMouseDownHandler ); _cP3.addEventListener(MouseEvent.MOUSE_DOWN , _cPMouseDownHandler ); _draw(); //速度とかメモリとかチェック(重要じゃないので無視無視) addChild(new Stats()); } private function _draw():void { /** * ポイントの番号は↓な感じ。 * 1--------2 * ---------- * ---------- * 3--------4 */ //初期状態のポイント取得 var aP0:Point = _cP0.initPoint; var aP1:Point = _cP1.initPoint; var aP2:Point = _cP2.initPoint; var aP3:Point = _cP3.initPoint; //初期状態のポイントよりマトリックス取得 var initMatrix1:Matrix = _getTransformMatrix( aP0 , aP1 , aP2 ); var initMatrix2:Matrix = _getTransformMatrix( aP3 , aP2 , aP1 ); //変更状態のポイント取得 var bP0:Point = new Point(_cP0.x , _cP0.y ); var bP1:Point = new Point(_cP1.x , _cP1.y ); var bP2:Point = new Point(_cP2.x , _cP2.y ); var bP3:Point = new Point(_cP3.x , _cP3.y ); //変更状態のポイントよりマトリックス取得 var editMatrix1:Matrix = _getTransformMatrix( bP0 , bP1 , bP2 ); var editMatrix2:Matrix = _getTransformMatrix( bP3 , bP2 , bP1 ); //初期状態と変更状態のマトリックスを合体 var newMatrix1:Matrix = initMatrix1.clone(); newMatrix1.concat(editMatrix1); var newMatrix2:Matrix = initMatrix2.clone(); newMatrix2.concat(editMatrix2); //マトリックスを適応 _canvas.graphics.clear(); //分割した1個目を描画 _canvas.graphics.lineStyle(1 , 0x00FF00); _canvas.graphics.beginBitmapFill(_bmd , newMatrix1 ); _canvas.graphics.moveTo(bP0.x , bP0.y ); _canvas.graphics.lineTo(bP1.x , bP1.y ); _canvas.graphics.lineTo(bP2.x , bP2.y ); _canvas.graphics.endFill(); //分割した2個目を描画 _canvas.graphics.lineStyle(1 , 0x00FF00); _canvas.graphics.beginBitmapFill(_bmd , newMatrix2 ); _canvas.graphics.moveTo(bP3.x , bP3.y ); _canvas.graphics.lineTo(bP1.x , bP1.y ); _canvas.graphics.lineTo(bP2.x , bP2.y ); _canvas.graphics.endFill(); } private function _getTransformMatrix($pt0:Point, $pt1:Point, $pt2:Point):Matrix { /* http://www.adobe.com/jp/devnet/flash/articles/matrix_class.html a: 水平方向の伸縮率 = 変換後の幅/もとの幅 b: 垂直方向の傾斜率 = 垂直方向の傾斜/もとの幅 c: 水平方向の傾斜率 = 水平方向の傾斜/もとの高さ d: 垂直方向の伸縮率 = 変換後の高さ/もとの高さ tx: 水平方向の移動ピクセル数 ty: 垂直方向の移動ピクセル数 */ var w:Number = _bmd.width; var h:Number = _bmd.height; var mat:Matrix = new Matrix(); mat.a = ($pt1.x - $pt0.x) / w; mat.b = ($pt1.y - $pt0.y) / w; mat.c = ($pt2.x - $pt0.x) / h; mat.d = ($pt2.y - $pt0.y) / h; mat.tx = $pt0.x; mat.ty = $pt0.y; return mat; } //こっからマウスのドラッグとかの設定(無視無視) private function _cPMouseDownHandler(e:MouseEvent):void { CirclePoint(e.target).startDrag(); CirclePoint(e.target).addEventListener(MouseEvent.MOUSE_MOVE , _cPMouseMoveHandler ); stage.addEventListener(MouseEvent.MOUSE_UP , _cPMouseUpHandler ); } private function _cPMouseUpHandler(e:MouseEvent):void { CirclePoint(e.target).stopDrag(); CirclePoint(e.target).removeEventListener(MouseEvent.MOUSE_MOVE , _cPMouseMoveHandler ); stage.removeEventListener(MouseEvent.MOUSE_UP , _cPMouseUpHandler ); } private function _cPMouseMoveHandler(e:MouseEvent):void { _draw(); } } } import flash.display.Bitmap; import flash.display.Shape; import flash.display.BitmapData; import flash.display.Sprite; import flash.geom.Point; /** * 赤い点を書いてる。 * それと初期状態のポイントをinitPointに保持してる。 */ class CirclePoint extends Sprite { public var initPoint:Point; public function CirclePoint($x:Number , $y:Number) { this.x = $x; this.y = $y; this.initPoint = new Point( $x , $y ); this.graphics.beginFill(0xFF0000,1); this.graphics.drawCircle(0,0,10); this.graphics.endFill(); this.buttonMode = true; } } /** * このTestImageクラスは画像の代わりに無理矢理、 * BitmapDataを作成してるだけなので無視無視無視無視無視。 */ class TestImage extends Bitmap { private var _w:Number = 200; private var _h:Number = 200; public function TestImage():void { var s:Shape = new Shape(); s.graphics.beginFill(0xCCCCCC , 1 ); s.graphics.drawRect(0,0,_w,_h); s.graphics.beginFill(0xFCFCFC , 1 ); s.graphics.drawRoundRect(30 , 30 , 30 , 10 , 20 ,20); s.graphics.drawRoundRect(140 , 30 , 30 , 10 , 20 ,20); s.graphics.drawCircle(50,70,10); s.graphics.drawCircle(150,70,10); s.graphics.drawCircle(75,120,5); s.graphics.drawCircle(125,120,5); s.graphics.drawRoundRect(40 , 170 , 120 , 10 , 20 ,20); s.graphics.endFill(); var bmd:BitmapData = new BitmapData(_w,_h); bmd.draw(s); this.bitmapData = bmd; } }