/**
* Copyright KinkumaDesign ( http://wonderfl.net/user/KinkumaDesign )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ggG5
*/
/*
* コンパイルしようとしたらfl.motion.BezierSegmentが
* ないっていわれてコンパイルできんかった、、。
* できたやつはブログにアップしておきました。
* http://www.kuma-de.com/blog/2010-04-14/1813
*/
package
{
import fl.motion.BezierSegment;
import flash.display.DisplayObject;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Point;
/**
* Cubic Bezier Curve like Illustrator
* Illustratorのような3次ベジェ曲線
*
* @see ベジエ曲線の仕組み (3) - 3次ベジエ曲線(てっく煮)
* http://d.hatena.ne.jp/nitoyon/20070920/bezier_3
*
* @see 滑らかな3次ベジェでゆらゆら曲線を描く(FICC LABS)
* http://www.ficc.jp/labs/archives/akira/3d_beizer/
*
* @author KinkumaDesign
*/
[SWF(width="450", height="450", frameRate="30", backgroundColor="0xffffff")]
public class LineSprite extends Sprite
{
private var segments:Array;
private var numSegments:int = 5;
public function LineSprite()
{
segments = [];
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
addEventListener(Event.ENTER_FRAME, update);
var segment:Segment;
var tx:Number, ty:Number;
var hw:Number = stage.stageWidth / 2;
var hh:Number = stage.stageHeight / 2;
var tRad:Number = Math.PI * 2 / numSegments;
for (var i:int = 0; i < numSegments; i++) {
tx = hw + Math.cos(tRad * i) * (hw - 50);
ty = hh + Math.sin(tRad * i) * (hh - 50);
segment = new Segment(new Point(tx, ty), Math.random() * 2 * Math.PI, Math.random() * 100 + 10);
addChild(segment);
segments.push(segment);
}
}
public function update(e: Event):void
{
var i:int;
var p0:Point, p1:Point, p2:Point, p3:Point;
var seg0:Segment;
var seg1:Segment;
var cnt:int = numSegments - 1;
while (cnt > -1) {
seg0 = segments[cnt];
seg0.update();
cnt--;
}
var g:Graphics = this.graphics;
g.clear();
g.lineStyle(1, 0x666666);
for (i = 0; i < numSegments - 1; i++) {
seg0 = segments[i];
seg1 = segments[i + 1];
p0 = seg0.anchorPos;
p1 = seg0.handle1Pos;
p2 = seg1.handle0Pos;
p3 = seg1.anchorPos;
drawBezier(p0, p1, p2, p3, g);
}
}
private function drawBezier(p0:Point, p1:Point, p2:Point, p3:Point, g:Graphics):void
{
var bezier:BezierSegment = new BezierSegment(p0, p1, p2, p3);
var numSplit:int = 30;
var i:int;
var t:Number = 1 / numSplit;
var drawPt:Point;
g.moveTo(p0.x, p0.y);
for (i = 1; i <= numSplit; i++) {
drawPt = bezier.getValue(t * i);
g.lineTo(drawPt.x, drawPt.y);
}
}
}
}
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;
class Segment extends Sprite
{
private var _handleAngle:Number; //傾き
private var _handleHalfLen:Number;
private var _handle0:ControlPoint;
private var _handle1:ControlPoint;
private var _anchor:ControlPoint;
public function Segment(anchorPoint:Point, handleAngle:Number, handleHalfLength:Number)
{
_anchor = new ControlPoint(0x4F80FF, 2, true);
addChild(_anchor);
_anchor.x = anchorPoint.x;
_anchor.y = anchorPoint.y;
_handle0 = new ControlPoint(0x4F80FF, 2);
addChild(_handle0);
_handle1 = new ControlPoint(0x4F80FF, 2);
addChild(_handle1);
this.handleAngle = handleAngle;
this.handleHalfLength = handleHalfLength;
}
public function set handleHalfLength(value:Number):void
{
_handleHalfLen = value;
}
public function set handleAngle(value:Number):void
{
_handleAngle = value;
}
public function get handle0Pos():Point
{
return new Point(_handle0.x, _handle0.y);
}
public function get handle1Pos():Point
{
return new Point(_handle1.x, _handle1.y);
}
public function get anchorPos():Point
{
return new Point(_anchor.x, _anchor.y);
}
public function set anchorPos(pos:Point):void
{
_anchor.x = pos.x;
_anchor.y = pos.y;
}
public function update():void
{
if (_handle0.isDragging || _handle1.isDragging) {
updateHandlePositionByDrag();
}else {
updateHandlePosition();
}
draw();
}
private function updateHandlePosition():void
{
var dx:Number = Math.cos(_handleAngle) * _handleHalfLen;
var dy:Number = Math.sin(_handleAngle) * _handleHalfLen;
_handle0.x = -dx + _anchor.x;
_handle0.y = -dy + _anchor.y;
_handle1.x = dx + _anchor.x;
_handle1.y = dy + _anchor.y;
}
private function updateHandlePositionByDrag():void
{
var baseHandle:ControlPoint;
var moveHandle:ControlPoint;
if (_handle0.isDragging) {
baseHandle = _handle0;
moveHandle = _handle1;
}else if(_handle1.isDragging){
baseHandle = _handle1;
moveHandle = _handle0;
}
var dx:Number = _anchor.x - baseHandle.x;
var dy:Number = _anchor.y - baseHandle.y;
_handleAngle = Math.atan2(dy, dx);
if (baseHandle == _handle1) {
_handleAngle += Math.PI;
}
_handleHalfLen = Math.sqrt(dx * dx + dy * dy);
moveHandle.x = dx + _anchor.x;
moveHandle.y = dy + _anchor.y;
}
public function draw():void
{
var g:Graphics = this.graphics;
g.clear();
g.lineStyle(1, 0x4F80FF);
g.moveTo(_handle0.x, _handle0.y);
g.lineTo(_handle1.x, _handle1.y);
}
}
class ControlPoint extends Sprite
{
private var _isDragging:Boolean = false;
public function ControlPoint(color:int = 0xff0000, size:int = 3, isAnchor:Boolean = false)
{
var g:Graphics = this.graphics;
if (isAnchor) {
g.lineStyle(1, color);
}else {
g.beginFill(color, 1);
}
g.drawCircle(0, 0, size);
g.endFill();
g.lineStyle(0,0,0);
g.beginFill(0, 0);
g.drawCircle(0, 0, 5);
g.endFill();
addEventListener(MouseEvent.MOUSE_DOWN, downHD);
buttonMode = true;
}
private function downHD(e:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_UP, upHD);
startDrag(false);
_isDragging = true;
}
private function upHD(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, upHD);
stopDrag();
_isDragging = false;
}
public function get isDragging():Boolean
{
return _isDragging;
}
}