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

forked from: GraphLayout

元ネタ:http://java.sun.com/applets/jdk/1.4/demo/applets/GraphLayout/example3.html
(操作)左ドラッグ:ノードを移動(移動後、固定)
    左クリック+シフト:固定状態を解除
Get Adobe Flash player
by hacker_mttcef7h 31 Jan 2010
// forked from termat's GraphLayout
package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.display.GradientType;
	import flash.geom.Matrix;
	import flash.text.TextField;
	import flash.text.TextFormat;

	/*
		元ネタ:http://java.sun.com/applets/jdk/1.4/demo/applets/GraphLayout/example3.html
		(操作)左ドラッグ:ノードを移動(移動後、固定)
		    左クリック+シフト:固定状態を解除
	*/
	
	[SWF(framerate="30",width="480",height="480",backgroundColor="0xffffff")]
	public class Practice07 extends Sprite{
		private var nodes:Vector.<Node>;
		private var edges:Vector.<Edge>;
		private var rect:Rectangle = new Rectangle(0, 0, 480, 480);
		private var baseLen:Number = 40;
		private var limit:Number = 10;
		private var pick:Node = null;
		private var text:TextField;
		
		public function Practice07():void {
			nodes = new Vector.<Node>();
			edges = new Vector.<Edge>();
			text = new TextField();
			var format:TextFormat = new TextFormat();
			format.size = 14;
			format.bold = true;
			text.defaultTextFormat = format;
			addChild(text);
			stage.addEventListener(Event.ENTER_FRAME, onFrame);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
			var str:String = "zero-one,zero-two,zero-three,zero-four,zero-five,zero-six,zero-seven,zero-eight,zero-nine,one-ten,two-twenty,three-thirty,four-fourty,five-fifty,six-sixty,seven-seventy,eight-eighty,nine-ninety,ten-twenty/80,twenty-thirty/80,thirty-fourty/80,fourty-fifty/80,fifty-sixty/80,sixty-seventy/80,seventy-eighty/80,eighty-ninety/80,ninety-ten/80,one-two/30,two-three/30,three-four/30,four-five/30,five-six/30,six-seven/30,seven-eight/30,eight-nine/30,nine-one/30";
			init(str);
		}
		
		private function init(str:String):void {
			var s1:Array = str.split(",");
			for each(var s:String in s1) {
				var s2:Array = s.split("-");
				var ii:int = (s2[1] as String).indexOf("/");
				if (ii < 0) {
					addEdge(s2[0] as String,s2[1] as String,baseLen);
				}else {
					var sx:Array = (s2[1] as String).split("/");
					addEdge(s2[0] as String,sx[0] as String,parseFloat(sx[1] as String));
				}
			}
		}
		
		private function onFrame(evt:Event): void {
			relax();
			graphics.clear();
			for each(var e:Edge in edges) {
				var x1:Number = nodes[e.from].x;
				var y1:Number = nodes[e.from].y;
				var x2:Number = nodes[e.to].x;
				var y2:Number = nodes[e.to].y;
				var len:Number = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) - e.len;
				if (len < 20) {
					graphics.lineStyle(1, 0xaaaaaa);
				}else {
					graphics.lineStyle(1, 0xff0000);
				}
				graphics.moveTo(nodes[e.from].x, nodes[e.from].y);
				graphics.lineTo(nodes[e.to].x, nodes[e.to].y);
			}
			for each(var n:Node in nodes) {
				if (n.fixed) {
					graphics.lineStyle(2, 0x0000ff);
					graphics.drawCircle(n.x, n.y, n.radius + 2);
				}
			}
			if (pick != null) {
				graphics.lineStyle(2, 0xFF0000);
				graphics.drawCircle(pick.x, pick.y, pick.radius + 2);
				text.x = pick.x+pick.radius;
				text.y = pick.y - pick.radius;
				text.text = pick.name;
			}
		}
		
		private function onMouseDown(e:MouseEvent):void {
			for each(var n:Node in nodes) {
				if (n.isContain(e.stageX, e.stageY)) {
					if (e.shiftKey) {
						if (n.fixed) n.fixed = false;
					}else {
						pick = n;
						pick.fixed = true;
					}
					return;
				}
			}
			pick = null;
		}
		
		private function onMouseUp(e:MouseEvent):void {
			pick = null;
			text.text = "";
		}
		
		private function onMouseMove(e:MouseEvent):void {
			if (pick == null) return;
			pick.x = e.stageX;
			pick.y = e.stageY;
		}
		
		private function relax():void {
			for (var i:int = 0; i < edges.length; i++) {
				var e:Edge = edges[i];
				var vx:Number = nodes[e.to].x - nodes[e.from].x;
				var vy:Number = nodes[e.to].y - nodes[e.from].y;
				var len:Number = Math.sqrt(vx * vx + vy * vy);
				len = Math.max(len, 0.001);
				var f:Number = (edges[i].len - len) / (len * 3);
				var dx:Number = f * vx;
				var dy:Number = f * vy;
				nodes[e.to].dx += dx;
				nodes[e.to].dy += dy;
				nodes[e.from].dx += -dx;
				nodes[e.from].dy += -dy;
			}
			for (i = 0; i < nodes.length; i++) {
				var n1:Node = nodes[i];
				dx = 0;
				dy = 0;
				for (var j:int = 0; j < nodes.length; j++) {
					if(i==j)continue;
					var n2:Node = nodes[j];
					vx = n1.x - n2.x;
					vy = n1.y - n2.y;
					len = vx * vx + vy * vy;
					if (len == 0) {
						dx += Math.random();
						dy += Math.random();
					} else if (len < 100*100) {
						dx += vx / len;
						dy += vy / len;
					}
				}
				var dlen:Number = dx * dx + dy * dy;
				if (dlen > 0) {
					dlen = Math.sqrt(dlen) / 2;
					n1.dx += dx / dlen;
					n1.dy += dy / dlen;
				}
			}
			for (i=0;i<nodes.length;i++){
				var n:Node = nodes[i];
				if (!n.fixed) {
					var ll:Number = Math.max(1.5, limit / n.neigh);
					n.x += Math.max(-ll, Math.min(ll, n.dx));
					n.y += Math.max(-ll, Math.min(ll, n.dy));
				}
				if (n.x < 0) {
					n.x = 0;
				} else if (n.x > rect.width) {
					n.x = rect.width;
				}
				if (n.y < 0) {
					n.y = 0;
				} else if (n.y > rect.height) {
					n.y = rect.height;
				}
				n.dx /= 2;
				n.dy /= 2;
			}
		}

		private function findNode(name:String):int {
			for (var i:int = 0; i < nodes.length; i++) {
				if (nodes[i].name == name) return i;
			}
			return addNode(name,rect.width*Math.random(),rect.height*Math.random());
		}
		
		private function addNode(name:String,nx:Number,ny:Number):int {
			var n:Node = new Node();
			n.name = name;
			n.x = nx;
			n.y = ny;
			nodes.push(n);
			addChild(n);
			return nodes.length - 1;
		}
		
		private function addEdge(name0:String,name1:String,len:Number):void {
			var e:Edge = new Edge();
			e.from = findNode(name0);
			e.to = findNode(name1);
			e.len = len;
			nodes[e.from].neigh++;
			nodes[e.to].neigh++;
			edges.push(e);
		}
	}

}
import flash.display.GradientType;
import flash.display.InterpolationMethod;
import flash.display.MovieClip;
import flash.display.SpreadMethod;
import flash.geom.Matrix;
import flash.text.TextField;
class Node extends MovieClip {
	public var dx:Number=0;
	public var dy:Number=0;
	public var neigh:int = 0;
	public var fixed:Boolean = false;
	public var radius:Number = 10;
	
	public function Node():void {
		var matrix:Matrix = new Matrix(); 
		matrix.createGradientBox(radius * 2, radius, Math.PI / 2, x - radius * 0.5, y - radius * 0.8);
		var c:int = Math.floor(Math.random() * 0xffffff);
		var c2:int = Math.min(c * 1.2, 0xffffff);
		var colors:Array = [c, c2];
		var alphas:Array = [0.8, 0.2];
		var ratios:Array = [0,255];
		graphics.beginFill(c);
		graphics.drawCircle(x, y, radius);
		graphics.beginGradientFill(GradientType.RADIAL, colors,alphas,ratios,matrix,
			SpreadMethod.PAD, InterpolationMethod.LINEAR_RGB, 0);
		graphics.drawEllipse(x - radius * 0.5, y - radius * 0.8, radius , radius * 0.5);
		graphics.endFill();
	}
	
	public function isContain(px:Number, py:Number):Boolean {
		var vx:Number = px - x;
		var vy:Number = py - y;
		return ((radius * radius - (vx * vx + vy * vy)) > 0);
	}
}

class Edge extends MovieClip{
	public var from:int = 0;
	public var to:int = 0;
	public var len:Number = 0;
}