In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

HEART-MAKER

----------------------------------
昨晩つくった線分上のドラッグ試作プログラム「線分AB上のアリア」
(cf: http://wonderfl.net/code/553e5fb0b2dbc9b6b088bf8fae5f8d5fcff0a50c )
のハート形アイコンがあまりにもカッコ悪かったので、
応用としてハート形をデザインするツールを仕立ててみました
制御点をドラッグして、あなた好みのハート形を作ってください
----------------------------------
Get Adobe Flash player
by tenasaku 28 Mar 2010
/**
 * Copyright tenasaku ( http://wonderfl.net/user/tenasaku )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/wNnB
 */

/*	----------------------------------
	昨晩つくった線分上のドラッグ試作プログラム「線分AB上のアリア」
	(cf: http://wonderfl.net/code/553e5fb0b2dbc9b6b088bf8fae5f8d5fcff0a50c )
	のハート形アイコンがあまりにもカッコ悪かったので、
	応用としてハート形をデザインするツールを仕立ててみました
	制御点をドラッグして、あなた好みのハート形を作ってください
	---------------------------------- */


package {

	import flash.display.*;
	import flash.events.*;

	public class Main extends Sprite {

		private var cp:Array; // 制御点 [0..7] の配列 (表示オブジェクト)
		private var fp:Array; // 通過点 [0..7] の配列 (表示オブジェクトまたはnull)
		private var tt:Array; // 通過点の重心座標の配列 (Number)
		private var frame:Sprite; // 制御点を結ぶガイド線分のレイヤー
		private var dragFP:int; // ドラッグ中の通過点の添字
		private function draw():void {
			var i:int;
			// 背景の消去と再着色
			this.graphics.clear();
			this.graphics.lineStyle(NaN);
			this.graphics.beginFill(0x99ffcc);
			this.graphics.drawRect(0,0,465,465);
			this.graphics.endFill();
			// ガイド線分の描画
			frame.graphics.clear();
			frame.graphics.lineStyle(0,0x669966);
			frame.graphics.moveTo(cp[0].x,cp[0].y);
			for ( i = 7 ; i >= 0 ; --i ) {
				frame.graphics.lineTo(cp[i].x, cp[i].y);
			}
			// 通過点の位置の算出
			for each ( i in [ 1, 2, 5, 6 ] ) {
				fp[i].x = (1-tt[i])*cp[i].x + tt[i]*cp[(i+1)%8].x;
				fp[i].y = (1-tt[i])*cp[i].y + tt[i]*cp[(i+1)%8].y;
			}
			// ハート型領域の再描画
			this.graphics.lineStyle(NaN);
			this.graphics.beginFill(0xff99cc);
			this.graphics.moveTo(cp[0].x, cp[0].y);
			this.graphics.curveTo(cp[1].x, cp[1].y, fp[1].x, fp[1].y);
			this.graphics.curveTo(cp[2].x, cp[2].y, fp[2].x, fp[2].y);
			this.graphics.curveTo(cp[3].x, cp[3].y, cp[4].x, cp[4].y);
			this.graphics.curveTo(cp[5].x, cp[5].y, fp[5].x, fp[5].y);
			this.graphics.curveTo(cp[6].x, cp[6].y, fp[6].x, fp[6].y);
			this.graphics.curveTo(cp[7].x, cp[7].y, cp[0].x, cp[0].y);
			this.graphics.endFill();
		}

		// 
		private function onMouseDownAtCP(e:MouseEvent):void {
			var i:int;
			for ( i = 0 ; i < 8 ; ++i ) {
				if ( cp[i].isPointedBy(e) ) {
					cp[i].startDrag();
					stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveAtCP);
					stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpAtCP);
					break;
				}
			}
		}

		private function onMouseDownAtFP(e:MouseEvent):void {
			var i:int;
			for each ( i in [ 1, 2, 5, 6 ] ) {
				if ( fp[i].isPointedBy(e) ) {
					if ((cp[i].x == cp[(i+1)%8].x)&&(cp[i].y == cp[(i+1)%8].y)) {
						// 線分の両端が一致している(=線分がない)ときは一方の端点をドラッグする
						cp[i].startDrag();
						stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveAtCP);
						stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpAtCP);
					} else { // 線分がちゃんとあるときは
						// 線分上に束縛されたドラッグを開始する
						dragFP = i;
						stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveAtFP);
						stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpAtFP);
					}
					break;
				}
			}
		}

		// 制御点オブジェクトのドラッグは通常のドラッグ処理
		private function onMouseMoveAtCP(e:MouseEvent):void {
			e.updateAfterEvent();
			this.draw();
		}

		// 通過点オブジェクトのドラッグは線分上に束縛される
		private function onMouseMoveAtFP(e:MouseEvent):void {
			var ax:Number = cp[(dragFP+1)%8].x - cp[dragFP].x;
			var ay:Number = cp[(dragFP+1)%8].y - cp[dragFP].y; 
			var bx:Number = e.stageX - cp[dragFP].x;
			var by:Number = e.stageY - cp[dragFP].y; 
			var t:Number = (ax*bx+ay*by)/(ax*ax+ay*ay);
			if ( t < 0 ) {
				tt[dragFP] = 0;
			} else if ( t > 1 ) {
				tt[dragFP] = 1;
			} else {
				tt[dragFP] = t;
			}
			e.updateAfterEvent();
			this.draw();
		}

		// 制御点オブジェクトのドラッグ終了処理
		private function onMouseUpAtCP(e:MouseEvent):void {
			var i:int;
			for ( i = 0 ; i < 8 ; ++i ) {
				cp[i].stopDrag();
			}
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveAtCP);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUpAtCP);
		}

		// 通過点オブジェクトのドラッグ終了処理
		private function onMouseUpAtFP(e:MouseEvent):void {
			dragFP = -1;
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveAtFP);
			stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUpAtFP);
		}

		private function initialize(e:Event):void {
			this.removeEventListener(Event.ADDED_TO_STAGE, initialize);
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			dragFP = -1;
			cp = new Array;
			fp = new Array;
			tt = new Array;
			frame = new Sprite();
			var i:int;
			for ( i = 0 ; i < 8 ; ++i ) {
				cp[i] = new BullsEye(0xff0000);
				if ( ( i == 1 )||( i == 2 )||( i == 5 )||( i == 6 ) ) {
					fp[i] = new BullsEye(0x0000ff);
					tt[i] = new Number(0);
				} else { // 使わない配列要素に(念のため)nullを入れる
					fp[i] = null;
					tt[i] = null;
				}
			}
			// 制御点 cp[i] の初期位置を設定
			cp[0].x = 232.5;		cp[0].y = 100;
			cp[1].x = 232.5+100;	cp[1].y =  50;
			cp[2].x = 232.5+200;	cp[2].y = 100;
			cp[3].x = 232.5+200;	cp[3].y = 250;
			cp[4].x = 232.5;		cp[4].y = 400;
			cp[5].x = 232.5-200;	cp[5].y = 250;
			cp[6].x = 232.5-200; cp[6].y = 100;
			cp[7].x = 232.5-100; cp[7].y =  50;
			// fp[i] の位置は直接指定せず 数値 tt[i] による重心座標で与える
			tt[1] = 0.5;
			tt[2] = 0.6;
			tt[5] = 0.4;
			tt[6] = 0.5;
			// ガイド線レイヤーオブジェクトを登録
			this.addChild(frame);
			// 制御点オブジェクトを登録
			for ( i = 0 ; i < 8 ; ++i ) {
				this.addChild(cp[i]);
			}
			// 通過点オブジェクトのほうが前面にくるように、あとで登録する
			for each ( i in [ 1, 2, 5, 6 ] ) {
				this.addChild(fp[i]);
			}
			// ドラッグへの反応のためのイベントリスナーを設定
			for ( i = 0 ; i < 8 ; ++i ) {
				cp[i].addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownAtCP);
			}
			for each ( i in [ 1, 2, 5, 6 ] ) {
				fp[i].addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownAtFP);
			}
			// 再描画
			draw();
		}

		public function Main():void {
			if ( stage != null ) {
				initialize(null);
			} else {
				this.addEventListener(Event.ADDED_TO_STAGE, initialize);
			}
		}

	} // end of class Main
} // end of package

import flash.display.*;
import flash.events.*;
import flash.geom.*;

// 点の標識として表示されるスプライトのクラス
// flash20100325b からの 使い回し
class BullsEye extends Sprite {
	public static const RADIUS:Number = 6;
	public static const DEFAULT_COLOR:uint = 0x000000;
	private var color:uint;
	public function draw():void {
		this.graphics.clear();
		this.graphics.beginFill(0xffffff);
		this.graphics.lineStyle(0,this.color);
		this.graphics.drawCircle(0,0,RADIUS);
		this.graphics.endFill();
		this.graphics.beginFill(this.color);
		this.graphics.drawCircle(0,0,RADIUS/5*3);
		this.graphics.endFill();
	}
	// MouseEventオブジェクトの座標を調べ, 自分がポイントされていたら true を返す
	public function isPointedBy(e:MouseEvent):Boolean {
		var mp:Point = new Point(e.stageX,e.stageY);
		var cp:Point = new Point(this.x,this.y);
		return ( Point.distance(cp,mp) <= RADIUS );
	}
	public function BullsEye(c:uint):void {
		this.color = c;
		this.draw();
	}
}