/** * click / hold pressed */ package{ import __AS3__.vec.Vector; import caurina.transitions.Tweener; import flash.display.GraphicsPathCommand; import flash.display.Shape; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point; import flash.filters.GlowFilter; [SWF(frameRate=60,backgroundColor="#000000")] public class CurveToTest extends Sprite{ private var commandsAry:Vector.<Vector.<int>>; private var dataAry:Vector.<Vector.<Number>>; private var gcAry:Vector.<GraphicsController>; private var gc:GraphicsController; private var maxLineNum:int = 20; private var segmentNum:int = 5; private var ctrlArea:Number = 100; private var flag:Boolean; private var velocity:Number = 0; public var _f:Number; public function CurveToTest(){ if(stage)init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(event:Event = null):void{ removeEventListener( Event.ADDED_TO_STAGE, init); gc = new GraphicsController(graphics); commandsAry = new Vector.<Vector.<int>>(); dataAry = new Vector.<Vector.<Number>>(); gcAry = new Vector.<GraphicsController>(); generateLines(); stage.addEventListener(MouseEvent.MOUSE_DOWN, changeTween); stage.addEventListener(MouseEvent.MOUSE_UP, changeTween); addEventListener(Event.ENTER_FRAME, enterFrameHandler); } private function generateLines():void{ var pos:Point = new Point(); var ctrlPos:Point = new Point(); var prevCtrl:Point = new Point(); for(var i:int;i<maxLineNum;i++){ var s:Shape = new Shape(); var commands:Vector.<int> = new Vector.<int>(); var data:Vector.<Number> = new Vector.<Number>(); var gc:GraphicsController = new GraphicsController(s.graphics); gc.thickness = Math.random()*4; gc.color = 0xFFFFFF; addChild(s); var oRadius:Number = Math.max(stage.stageWidth,stage.stageHeight); var radius:Number = oRadius; var rad:Number=0; for(var j:int=0;j<segmentNum;j++){ if(j==0){ rad = Math.random()*360 * Math.PI/180; pos.x = Math.cos(rad) * oRadius + stage.stageWidth/2; pos.y = Math.sin(rad) * oRadius + stage.stageHeight/2; commands.push(GraphicsPathCommand.WIDE_MOVE_TO); data.push(0,0,pos.x,pos.y); } else { rad = Math.random()*360 * Math.PI/180; ctrlPos.x = Math.cos(rad)*radius + stage.stageWidth/2; ctrlPos.y = Math.sin(rad)*radius + stage.stageHeight/2; radius -= oRadius/segmentNum; if(j==0){ prevCtrl.x = Math.random()*stage.stageWidth; prevCtrl.y = Math.random()*stage.stageHeight; } //最後は中央に if(j==segmentNum-1) pos = new Point(stage.stageWidth/2,stage.stageHeight/2); else pos = Point.interpolate(ctrlPos,prevCtrl,0.5); commands.push(GraphicsPathCommand.CURVE_TO); data.push(prevCtrl.x, prevCtrl.y, pos.x, pos.y); prevCtrl = ctrlPos.clone(); } } gcAry.push(gc); commandsAry.push(commands); dataAry.push(data); } } private function enterFrameHandler(event:Event):void{ } public function get f():Number{ return _f }; public function set f(value:Number):void{ _f = value; drawLines(); } private function drawLines():void{ for(var i:int=0;i<commandsAry.length;i++){ gcAry[i].drawLine(commandsAry[i],dataAry[i],_f); } } private function changeTween(event:MouseEvent):void{ if( flag ){ filters = [new GlowFilter(0x59B2E6,1,20,20,3,3)]; Tweener.addTween(this, { f:1, time:4 }); flag = false; } else { filters = [new GlowFilter(0x59B2E6,0,0,0,0,0)]; Tweener.addTween(this, { f:0, time:4 }); flag = true; } } } } import __AS3__.vec.Vector; import flash.display.Graphics; import flash.geom.Point; class GraphicsController{ private var g:Graphics; public var thickness:Number = 1; public var color:Number = 0x3388DD; public function GraphicsController(graphics:Graphics){ this.g = graphics; } /** * 弧をdrawPathで描画するためのデータを返します */ public function objectArc(radius:Number, degree:Number, opposite:Boolean=false):Object{ //最終的に返す値。 var commands:Vector.<int> = new Vector.<int>(); var data:Vector.<Number> = new Vector.<Number>(); if( Math.abs(degree) > 360 ) degree %= 360; var div:int = Math.ceil(degree/30); var radians:Number = degree * Math.PI / 180; var segment:Number = radians / div; var _from:Number; var _to:Number; for(var i:int;i<div;i++){ //曲線の分割 if( opposite ){ _from = ( i == 0 ) ? radians : segment * ( div - i ); _to = ( div - i - 1 ) * segment; } else { _from = segment * i; _to = (i == div-1) ? radians : segment * (i+1); } //初回ループ時に、最初の点に移動 if( i == 0 ){ var startPos:Point = new Point(); startPos.x = Math.cos(_from) * radius; startPos.y = Math.sin(_from) * radius; commands.push(2); data.push(startPos.x, startPos.y); } //終着点 var endPos:Point = new Point(); endPos.x = Math.cos(_to) * radius; endPos.y = Math.sin(_to) * radius; //コントロールポイント var controlPos:Point = new Point(); var basePos:Point = opposite ? endPos : startPos; var rotate:Number = opposite ? _to : _from; controlPos.y = radius * Math.tan(Math.abs(_to - _from)/2); controlPos.x = basePos.x - Math.sin(rotate) * controlPos.y; controlPos.y = basePos.y + Math.cos(rotate) * controlPos.y; //Vectorに格納 commands.push(3); data.push(controlPos.x, controlPos.y, endPos.x, endPos.y); //次のループのために始点を移動 startPos.x = endPos.x; startPos.y = endPos.y; } return { commands:commands, data:data }; } /** * 扇を描きます */ public function drawPie(degree:Number, radius:Number, innerRadius:Number = 0):void{ if(degree > 0){ g.clear(); g.beginFill(0x993300); //g.lineStyle(2,0xFF0000); var arc:Object = objectArc(radius,degree); if( innerRadius == 0 ){ arc.commands.push(2); arc.data.push(0,0); g.drawPath(arc.commands, arc.data); } else { var oppositeArc:Object = objectArc(innerRadius,degree,true); g.moveTo(radius, 0); g.drawPath(arc.commands, arc.data); oppositeArc.commands.push(2); oppositeArc.data.push(radius, 0); g.drawPath(oppositeArc.commands, oppositeArc.data); } } } /** * パスのトリミングをします */ public function drawLine(commands:Vector.<int>, data:Vector.<Number>,f:Number = 0.5):void{ g.clear(); g.lineStyle(thickness,color); var startPos:Point = new Point(data[2],data[3]); var endPos:Point = new Point(); var trimPos:Point = new Point(); var controlPoint:Point = new Point(); var eachLength:Vector.<Number> = new Vector.<Number>(); var com:Vector.<int> = commands.concat(); var dat:Vector.<Number> = data.concat(); //全ての曲線の長さの合計をとっておく(それぞれの長さも) //長さの算出は今のところ直線距離(改良予定) var totalLength:Number = 0; var i:int; for(i=1;i<commands.length;i++){ endPos.x = data[i*4+2]; endPos.y = data[i*4+3]; eachLength.push(Math.sqrt(Math.pow(endPos.x-startPos.x,2)+Math.pow(endPos.y-startPos.y,2))); totalLength += eachLength[i-1]; startPos.x = endPos.x; startPos.y = endPos.y; } var length:Number = 0; for(i=0;i<commands.length-1;i++){ if (length + eachLength[i] >= f*totalLength){ //その線分内での割合を算出 var _f:Number = (f*totalLength - length) / eachLength[i]; i++; if(i != 0){ startPos.x = dat[(i-1)*4+2]; startPos.y = dat[(i-1)*4+3]; } //コントロールポイント controlPoint.x = data[i*4]; controlPoint.y = data[i*4+1]; endPos.x = data[i*4+2]; endPos.y = data[i*4+3]; //分割 var trimCtrl:Point = Point.interpolate(controlPoint,startPos,_f); trimPos = Point.interpolate(Point.interpolate(endPos,controlPoint,_f),trimCtrl,_f); com.splice(i, com.length-i); dat.splice(i*4,dat.length-i*4); com.push(3); dat.push(trimCtrl.x,trimCtrl.y,trimPos.x,trimPos.y); g.drawPath(com,dat); i--; break; } else{ length += eachLength[i]; } } } } LightSketch(psyark respection)