fl.motion.BezierSegmentで三次ベジェ

fl.motion.BezierSegmentクラスを使用して三次ベジェ曲線を描く。

beziersegment.swf

BezierSegmentの分割数を変える為のコンポーネントを追加し、値を変えた時に再描画するようイベントリスナーを設置。
また、2個のアンカーと2個のハンドルを追加し、ドラッグ時に再描画するようイベントリスナを設置。

BezierSegmentクラスは、コンストラクタに2個のアンカーと2個のハンドルの座標をPointで渡してインスタンスを生成する。
BezierSegment.getValue(t);で媒介変数t=0〜1の値を順に渡していってtに相当する座標をPointで取得し、lineToで描画する。 今回は、t=0〜1を何分割するかをNumericStepperで切り替えるようにしてみた。

package {
	import fl.controls.NumericStepper;
	import fl.motion.BezierSegment;

	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	public class Main extends Sprite {

		private var curveLayer:Sprite;
		private var lineLayer:Sprite;
		private var interpolate:NumericStepper;
		private var base:MovieClip;

		private var a:Anchor;
		private var b:Handle;
		private var c:Handle;
		private var d:Anchor;

		private var interpolateNumber:int = 50;

		public function Main() {
			this.interpolate = new NumericStepper();
			this.interpolate.maximum = 100;
			this.interpolate.value = 50;
			this.interpolate.x = 470;
			this.interpolate.y = 528;
			this.interpolate.addEventListener(Event.CHANGE, this.onInterpolateChange);
			this.addChild(this.interpolate);

			this.base = this.getChildByName('_base') as MovieClip;

			this.initLayer();
			this.initControllPoints();
			this.draw();
		}

		private function get pointA():Point {return new Point(this.a.x, this.a.y);}
		private function set pointA(value:Point):void {this.a.x = value.x; this.a.y = value.y};
		private function get pointB():Point {return new Point(this.b.x, this.b.y);}
		private function set pointB(value:Point):void {this.b.x = value.x; this.b.y = value.y};
		private function get pointC():Point {return new Point(this.c.x, this.c.y);}
		private function set pointC(value:Point):void {this.c.x = value.x; this.c.y = value.y};
		private function get pointD():Point {return new Point(this.d.x, this.d.y);}
		private function set pointD(value:Point):void {this.d.x = value.x; this.d.y = value.y};

		private function initLayer():void {
			this.curveLayer = new Sprite();
			this.lineLayer = new Sprite();

			this.addChild(this.lineLayer);
			this.addChild(this.curveLayer);
		}

		private function initControllPoints():void {
			var movableRectangle:Rectangle = new Rectangle(4, 4, this.base.width - 8, this.base.height - 8);

			this.a = new Anchor(true);
			this.b = new Handle(true);
			this.c = new Handle(true);
			this.d = new Anchor(true);

			this.a.x = 100;
			this.a.y = this.stage.stageHeight - 100;
			this.a.movableRectangle = movableRectangle;
			this.a.addEventListener(DragEvent.DRAG_PROGRESS, this.onDragProgress);
			this.b.x = 100;
			this.b.y = 100;
			this.b.movableRectangle = movableRectangle;
			this.b.addEventListener(DragEvent.DRAG_PROGRESS, this.onDragProgress);
			this.c.x = this.stage.stageWidth - 100;
			this.c.y = 100;
			this.c.movableRectangle = movableRectangle;
			this.c.addEventListener(DragEvent.DRAG_PROGRESS, this.onDragProgress);
			this.d.x = this.stage.stageWidth - 100;
			this.d.y = this.stage.stageHeight - 100;
			this.d.movableRectangle = movableRectangle;
			this.d.addEventListener(DragEvent.DRAG_PROGRESS, this.onDragProgress);

			this.addChild(this.a);
			this.addChild(this.b);
			this.addChild(this.c);
			this.addChild(this.d);
		}

		private function onDragProgress(e:DragEvent):void {
			this.draw();
		}

		private function onInterpolateChange(e:Event):void {
			this.draw();
		}

		private function draw():void {
			this.drawLine();
			this.drawCurve();
		}

		private function drawLine():void {
			this.lineLayer.graphics.clear();
			this.lineLayer.graphics.lineStyle(1, 0xAAAAAA);
			this.lineLayer.graphics.moveTo(this.pointA.x, this.pointA.y);
			this.lineLayer.graphics.lineTo(this.pointB.x, this.pointB.y);
			this.lineLayer.graphics.moveTo(this.pointC.x, this.pointC.y);
			this.lineLayer.graphics.lineTo(this.pointD.x, this.pointD.y);
		}

		private function drawCurve():void {
			var bezierSegment:BezierSegment = new BezierSegment(this.pointA, this.pointB, this.pointC, this.pointD);
			var interpolate:int = this.interpolate.value;
			var timeUnit:Number = 1 / interpolate;
			var point:Point;

			this.curveLayer.graphics.clear();
			this.curveLayer.graphics.lineStyle(1, 0x333333);
			this.curveLayer.graphics.moveTo(bezierSegment.a.x, bezierSegment.a.y);
			for (var i:int = 0; i < interpolate; i++) {
				point = bezierSegment.getValue(timeUnit * (i + 1));
				this.curveLayer.graphics.lineTo(point.x, point.y);
			}
		}

	}
}
  1. package {
  2.     import fl.controls.NumericStepper;
  3.     import fl.motion.BezierSegment;
  4.  
  5.     import flash.display.MovieClip;
  6.     import flash.display.Sprite;
  7.     import flash.events.Event;
  8.     import flash.geom.Point;
  9.     import flash.geom.Rectangle;
  10.  
  11.     public class Main extends Sprite {
  12.  
  13.         private var curveLayer:Sprite;
  14.         private var lineLayer:Sprite;
  15.         private var interpolate:NumericStepper;
  16.         private var base:MovieClip;
  17.  
  18.         private var a:Anchor;
  19.         private var b:Handle;
  20.         private var c:Handle;
  21.         private var d:Anchor;
  22.  
  23.         private var interpolateNumber:int = 50;
  24.  
  25.         public function Main() {
  26.             this.interpolate = new NumericStepper();
  27.             this.interpolate.maximum = 100;
  28.             this.interpolate.value = 50;
  29.             this.interpolate.x = 470;
  30.             this.interpolate.y = 528;
  31.             this.interpolate.addEventListener(Event.CHANGE, this.onInterpolateChange);
  32.             this.addChild(this.interpolate);
  33.  
  34.             this.base = this.getChildByName('_base') as MovieClip;
  35.  
  36.             this.initLayer();
  37.             this.initControllPoints();
  38.             this.draw();
  39.         }
  40.  
  41.         private function get pointA():Point {return new Point(this.a.x, this.a.y);}
  42.         private function set pointA(value:Point):void {this.a.x = value.x; this.a.y = value.y};
  43.         private function get pointB():Point {return new Point(this.b.x, this.b.y);}
  44.         private function set pointB(value:Point):void {this.b.x = value.x; this.b.y = value.y};
  45.         private function get pointC():Point {return new Point(this.c.x, this.c.y);}
  46.         private function set pointC(value:Point):void {this.c.x = value.x; this.c.y = value.y};
  47.         private function get pointD():Point {return new Point(this.d.x, this.d.y);}
  48.         private function set pointD(value:Point):void {this.d.x = value.x; this.d.y = value.y};
  49.  
  50.         private function initLayer():void {
  51.             this.curveLayer = new Sprite();
  52.             this.lineLayer = new Sprite();
  53.  
  54.             this.addChild(this.lineLayer);
  55.             this.addChild(this.curveLayer);
  56.         }
  57.  
  58.         private function initControllPoints():void {
  59.             var movableRectangle:Rectangle = new Rectangle(4, 4, this.base.width - 8, this.base.height - 8);
  60.  
  61.             this.a = new Anchor(true);
  62.             this.b = new Handle(true);
  63.             this.c = new Handle(true);
  64.             this.d = new Anchor(true);
  65.  
  66.             this.a.x = 100;
  67.             this.a.y = this.stage.stageHeight - 100;
  68.             this.a.movableRectangle = movableRectangle;
  69.             this.a.addEventListener(DragEvent.DRAG_PROGRESS, this.onDragProgress);
  70.             this.b.x = 100;
  71.             this.b.y = 100;
  72.             this.b.movableRectangle = movableRectangle;
  73.             this.b.addEventListener(DragEvent.DRAG_PROGRESS, this.onDragProgress);
  74.             this.c.x = this.stage.stageWidth - 100;
  75.             this.c.y = 100;
  76.             this.c.movableRectangle = movableRectangle;
  77.             this.c.addEventListener(DragEvent.DRAG_PROGRESS, this.onDragProgress);
  78.             this.d.x = this.stage.stageWidth - 100;
  79.             this.d.y = this.stage.stageHeight - 100;
  80.             this.d.movableRectangle = movableRectangle;
  81.             this.d.addEventListener(DragEvent.DRAG_PROGRESS, this.onDragProgress);
  82.  
  83.             this.addChild(this.a);
  84.             this.addChild(this.b);
  85.             this.addChild(this.c);
  86.             this.addChild(this.d);
  87.         }
  88.  
  89.         private function onDragProgress(e:DragEvent):void {
  90.             this.draw();
  91.         }
  92.  
  93.         private function onInterpolateChange(e:Event):void {
  94.             this.draw();
  95.         }
  96.  
  97.         private function draw():void {
  98.             this.drawLine();
  99.             this.drawCurve();
  100.         }
  101.  
  102.         private function drawLine():void {
  103.             this.lineLayer.graphics.clear();
  104.             this.lineLayer.graphics.lineStyle(1, 0xAAAAAA);
  105.             this.lineLayer.graphics.moveTo(this.pointA.x, this.pointA.y);
  106.             this.lineLayer.graphics.lineTo(this.pointB.x, this.pointB.y);
  107.             this.lineLayer.graphics.moveTo(this.pointC.x, this.pointC.y);
  108.             this.lineLayer.graphics.lineTo(this.pointD.x, this.pointD.y);
  109.         }
  110.  
  111.         private function drawCurve():void {
  112.             var bezierSegment:BezierSegment = new BezierSegment(this.pointA, this.pointB, this.pointC, this.pointD);
  113.             var interpolate:int = this.interpolate.value;
  114.             var timeUnit:Number = 1 / interpolate;
  115.             var point:Point;
  116.  
  117.             this.curveLayer.graphics.clear();
  118.             this.curveLayer.graphics.lineStyle(1, 0x333333);
  119.             this.curveLayer.graphics.moveTo(bezierSegment.a.x, bezierSegment.a.y);
  120.             for (var i:int = 0; i < interpolate; i++) {
  121.                 point = bezierSegment.getValue(timeUnit * (i + 1));
  122.                 this.curveLayer.graphics.lineTo(point.x, point.y);
  123.             }
  124.         }
  125.  
  126.     }
  127. }

  • ActionScript
  • Anchor.as
  • Source
package {
	import flash.display.CapsStyle;
	import flash.display.JointStyle;
	import flash.display.LineScaleMode;

	public class Anchor extends DraggableSprite {

		public function Anchor(isDraggable:Boolean, rectSides:Number = 6, lineThickness:Number = 1, lineColor:uint = 0xAAAAAA, lineAlpha:Number = 1, fillColor:uint = 0xFFFFFF, fillAlpha:Number = 0.5) {
			super(isDraggable);

			this.graphics.lineStyle(lineThickness, lineColor, lineAlpha, false, LineScaleMode.NONE, CapsStyle.NONE, JointStyle.MITER, 3);
			this.graphics.beginFill(fillColor, fillAlpha);
			this.graphics.drawRect(-3, -3, rectSides, rectSides);
			this.graphics.endFill();
		}

	}
}
  1. package {
  2.     import flash.display.CapsStyle;
  3.     import flash.display.JointStyle;
  4.     import flash.display.LineScaleMode;
  5.  
  6.     public class Anchor extends DraggableSprite {
  7.  
  8.         public function Anchor(isDraggable:Boolean, rectSides:Number = 6, lineThickness:Number = 1, lineColor:uint = 0xAAAAAA, lineAlpha:Number = 1, fillColor:uint = 0xFFFFFF, fillAlpha:Number = 0.5) {
  9.             super(isDraggable);
  10.  
  11.             this.graphics.lineStyle(lineThickness, lineColor, lineAlpha, false, LineScaleMode.NONE, CapsStyle.NONE, JointStyle.MITER, 3);
  12.             this.graphics.beginFill(fillColor, fillAlpha);
  13.             this.graphics.drawRect(-3, -3, rectSides, rectSides);
  14.             this.graphics.endFill();
  15.         }
  16.  
  17.     }
  18. }

  • ActionScript
  • Handle.as
  • Source
package {

	public class Handle extends DraggableSprite {

		public function Handle(isDraggable:Boolean, circleRadius:Number = 3, fillColor:uint = 0xAAAAAA, fillAlpha:Number = 1) {
			super(isDraggable);

			this.graphics.beginFill(fillColor, fillAlpha);
			this.graphics.drawCircle(0, 0, circleRadius);
			this.graphics.endFill();
		}

	}
}
  1. package {
  2.  
  3.     public class Handle extends DraggableSprite {
  4.  
  5.         public function Handle(isDraggable:Boolean, circleRadius:Number = 3, fillColor:uint = 0xAAAAAA, fillAlpha:Number = 1) {
  6.             super(isDraggable);
  7.  
  8.             this.graphics.beginFill(fillColor, fillAlpha);
  9.             this.graphics.drawCircle(0, 0, circleRadius);
  10.             this.graphics.endFill();
  11.         }
  12.  
  13.     }
  14. }

  • ActionScript
  • DraggableSprite.as
  • Source
package {
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;

	public class DraggableSprite extends Sprite {

		private var _isDraggable:Boolean;

		public var movableRectangle:Rectangle;

		public function DraggableSprite(isDraggable:Boolean) {
			super();

			this.isDraggable = isDraggable;
			this.movableRectangle = new Rectangle();
		}

		public function get isDraggable():Boolean {
			return this._isDraggable;
		}

		public function set isDraggable(value:Boolean):void {
			this._isDraggable = value;

			if (this.isDraggable) {
				this.buttonMode = true;
				this.addEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown);
			} else {
				this.buttonMode = false;
				this.removeEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown);
			}
		}

		private function onMouseDown(e:MouseEvent):void {
			this.dispatchEvent(new DragEvent(DragEvent.DRAG_START));

			this.addEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
			this.stage.addEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
			this.stage.addEventListener(MouseEvent.MOUSE_MOVE, this.onStageMouseMove);

			this.startDrag(false, this.movableRectangle);
		}

		private function onMouseUp(e:MouseEvent):void {
			this.removeEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
			this.stage.removeEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
			this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, this.onStageMouseMove);

			this.stopDrag();

			this.dispatchEvent(new DragEvent(DragEvent.DRAG_PROGRESS));
			this.dispatchEvent(new DragEvent(DragEvent.DRAG_COMPLETE));
		}

		private function onStageMouseMove(e:MouseEvent):void {
			this.dispatchEvent(new DragEvent(DragEvent.DRAG_PROGRESS));
			e.updateAfterEvent();
		}

		public function removeAllEventListener():void {
			this.removeEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown);
			this.removeEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);

			if (this.stage != null) {
				this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, this.onStageMouseMove);
				this.stage.removeEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
			}
		}

	}
}
  1. package {
  2.     import flash.display.Sprite;
  3.     import flash.events.MouseEvent;
  4.     import flash.geom.Rectangle;
  5.  
  6.     public class DraggableSprite extends Sprite {
  7.  
  8.         private var _isDraggable:Boolean;
  9.  
  10.         public var movableRectangle:Rectangle;
  11.  
  12.         public function DraggableSprite(isDraggable:Boolean) {
  13.             super();
  14.  
  15.             this.isDraggable = isDraggable;
  16.             this.movableRectangle = new Rectangle();
  17.         }
  18.  
  19.         public function get isDraggable():Boolean {
  20.             return this._isDraggable;
  21.         }
  22.  
  23.         public function set isDraggable(value:Boolean):void {
  24.             this._isDraggable = value;
  25.  
  26.             if (this.isDraggable) {
  27.                 this.buttonMode = true;
  28.                 this.addEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown);
  29.             } else {
  30.                 this.buttonMode = false;
  31.                 this.removeEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown);
  32.             }
  33.         }
  34.  
  35.         private function onMouseDown(e:MouseEvent):void {
  36.             this.dispatchEvent(new DragEvent(DragEvent.DRAG_START));
  37.  
  38.             this.addEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
  39.             this.stage.addEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
  40.             this.stage.addEventListener(MouseEvent.MOUSE_MOVE, this.onStageMouseMove);
  41.  
  42.             this.startDrag(false, this.movableRectangle);
  43.         }
  44.  
  45.         private function onMouseUp(e:MouseEvent):void {
  46.             this.removeEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
  47.             this.stage.removeEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
  48.             this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, this.onStageMouseMove);
  49.  
  50.             this.stopDrag();
  51.  
  52.             this.dispatchEvent(new DragEvent(DragEvent.DRAG_PROGRESS));
  53.             this.dispatchEvent(new DragEvent(DragEvent.DRAG_COMPLETE));
  54.         }
  55.  
  56.         private function onStageMouseMove(e:MouseEvent):void {
  57.             this.dispatchEvent(new DragEvent(DragEvent.DRAG_PROGRESS));
  58.             e.updateAfterEvent();
  59.         }
  60.  
  61.         public function removeAllEventListener():void {
  62.             this.removeEventListener(MouseEvent.MOUSE_DOWN, this.onMouseDown);
  63.             this.removeEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
  64.  
  65.             if (this.stage != null) {
  66.                 this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, this.onStageMouseMove);
  67.                 this.stage.removeEventListener(MouseEvent.MOUSE_UP, this.onMouseUp);
  68.             }
  69.         }
  70.  
  71.     }
  72. }

  • ActionScript
  • DragEvent.as
  • Source
package {
	import flash.events.Event;

	public class DragEvent extends Event {

		public static const DRAG_START:String = 'dragStart';
		public static const DRAG_PROGRESS:String = 'dragProgress';
		public static const DRAG_COMPLETE:String = 'dragComplete';

		public function DragEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
			super(type, bubbles, cancelable);
		}

	}
}
  1. package {
  2.     import flash.events.Event;
  3.  
  4.     public class DragEvent extends Event {
  5.  
  6.         public static const DRAG_START:String = 'dragStart';
  7.         public static const DRAG_PROGRESS:String = 'dragProgress';
  8.         public static const DRAG_COMPLETE:String = 'dragComplete';
  9.  
  10.         public function DragEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
  11.             super(type, bubbles, cancelable);
  12.         }
  13.  
  14.     }
  15. }

実際に描画すると、45°の倍数の近傍の線がやたら細く見える。
これについては1pxの斜線で、実験してみた。


About this entry