forked from: Line Connection

by TIAGODJF forked from Line Connection (diff: 2)
♥0 | Line 341 | Modified 2012-07-31 07:25:50 | MIT License
play

ActionScript3 source code

/**
 * Copyright TIAGODJF ( http://wonderfl.net/user/TIAGODJF )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/tBe2
 */

// forked from gupon's Line Connection
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.TimerEvent;
    import flash.geom.Point;
    import flash.utils.Timer;
    
   [SWF(backgroundColor="#FFFFFF",frameRate="31")]
    public class LineConnection extends Sprite
    {
        private var prevPoint:Point;
        private var prevCore:LineCore;
        private var core:LineCore;
        private var point:Point;
        private var gc:GraphicsController;
        private var numLines:int = 5;
        private var lineGCs:Vector.<GraphicsController>;
        private var lineShapes:Vector.<Shape>;
        private var numSegment:int = 3;
        
        public function LineConnection()
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(event:Event=null):void{
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            lineGCs = new Vector.<GraphicsController>();
            lineShapes = new Vector.<Shape>();
            
            point = new Point( Math.random()*stage.stageWidth, Math.random()*stage.stageHeight);
            moveNext();
            
            var timer:Timer = new Timer(1500);
            timer.addEventListener(TimerEvent.TIMER, timerHandler);
            timer.start();
        }
        
        private function timerHandler(event:TimerEvent):void{
            moveNext();
        }
        
        private function moveNext():void{
            prevPoint = point.clone();
            if( core ){
                core.addEventListener(Event.COMPLETE,function(event:Event):void{
                    event.target.removeEventListener( event.type, arguments.callee);
                    removeChild(LineCore(event.target));
                });
                core.disappear();
            }
            core = new LineCore(Math.random()*50 + 20);
            do{
                point = new Point( Math.random()*stage.stageWidth*2, Math.random()*stage.stageHeight*2);
            } while ( Point.distance( prevPoint, point ) < 300 )
            core.x = point.x;
            core.y = point.y;
            
            generateLines();
            addChild(core);
        }
        
        private function generateLines():void{
            var radius:Number = Point.distance(prevPoint, point)/numSegment*1.5;
            
            for each( var shape:Shape in lineShapes ) removeChild(shape);
            lineGCs.splice(0,numLines);
            lineShapes.splice(0,numLines);
            
            for(var i:int=0;i<numLines;i++){
                var s:Shape = new Shape();
                var gc:GraphicsController = new GraphicsController(s.graphics);
                var commands:Vector.<int> = new Vector.<int>();
                var data:Vector.<Number> = new Vector.<Number>();
                lineGCs.push(gc);
                lineShapes.push(s);
                gc.thickness = Math.random()*5;
                gc.color = 0xBB0000;
                commands.push(GraphicsPathCommand.WIDE_MOVE_TO);
                data.push(0, 0, prevPoint.x, prevPoint.y);
                
                var prevCtrl:Point = prevPoint.add(new Point(Math.random()*radius,Math.random()*radius));
                for(var j:int=0;j<numSegment;j++){
                    var basePoint:Point = Point.interpolate(prevPoint, point, 1 - (j+1)/numSegment);
                    var ctrl:Point = basePoint.add(new Point(Math.random()*radius - radius/2,Math.random()*radius - radius/2));
                    var pos:Point;
                    if( j == numSegment-1) pos = point;
                    else pos = Point.interpolate(prevCtrl, ctrl, .5);
                    data.push( prevCtrl.x, prevCtrl.y, pos.x, pos.y);
                    commands.push(GraphicsPathCommand.CURVE_TO);
                    prevCtrl = ctrl.clone();
                }
                addChild(s);
                gc.drawLine(commands,data,0);
                Tweener.addTween(gc, { f:1, time:1.5, transition :"easeOutQuint"});
                Tweener.addTween(gc, { f0:1, time:1.5, transition:"easeInQuint"});
            }
            Tweener.addTween(this,{x:stage.stageWidth/2 - point.x, y:stage.stageHeight/2 - point.y, time:1.5});
        }
    }
}


        import __AS3__.vec.Vector;
    
    import caurina.transitions.Tweener;
    import caurina.transitions.properties.DisplayShortcuts;
    
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;
    
    class LineCore extends Sprite {
        private var num:int;
        private var color:uint;
        private var radius:Number;
        private var weight:Number;
        private var gcAry:Vector.<GraphicsController>;
        
        public function LineCore(radius:Number=20, weight:Number=10, num:int=5, color:uint=0x555555){
            this.radius = radius;
            this.weight = weight;
            this.num = num;
            this.color = color;
            makePies();
            addAppearMotion();
            
            graphics.beginFill(0xFF0000);
            graphics.drawCircle(0,0,5);
            addEventListener(Event.ENTER_FRAME, enterFrameHandler);
        }
        
        private function makePies():void{
            gcAry = new Vector.<GraphicsController>;
            
            for(var i:int=0;i<num;i++){
                var s:Shape = new Shape();
                var gc:GraphicsController = new GraphicsController(s.graphics);
                gcAry.push(gc);
                gc.color = color;
                gc.drawPie( 0, 0, 0);
                s.rotation = i * 360 / num;
                addChild(s);
            }
        }
        
        private function addAppearMotion():void{
            for(var i:int=0;i<gcAry.length;i++){
                var gc:GraphicsController = gcAry[i];
                Tweener.addTween(gc, { degree:360/num - 5, radius:radius, time:.5, delay:i*.2 });
                Tweener.addTween(gc, { innerRadius:radius-weight, time:1, delay:i*.2, transition:"easeOutQuint" });
            }
            Tweener.addTween(this, {rotation:120, time:1.8 });
        }
        
        public function disappear():void{
            for(var i:int=0;i<gcAry.length;i++){
                var gc:GraphicsController = gcAry[i];
                if( i == 0 ){
                    Tweener.addTween(gc, { degree:360, radius:radius*1.2, innerRadius:0, time:1});
                    
                } else {
                    Tweener.addTween(gc, { innerRadius:radius, time:.5, delay:i*.1 });
                }
            }
            DisplayShortcuts.init();
            Tweener.addTween(this, {rotation:359, time:1, transition:"linear" });
            Tweener.addTween(this, { _scale:0, time:.5, delay:.5, transition:"easeInQuint", onComplete:dispatch });
            
            function dispatch():void{
                dispatchEvent( new Event( Event.COMPLETE ));
            }
        }
        
        private function enterFrameHandler(event:Event):void{
            
        }
    }


    import __AS3__.vec.Vector;
    
    import flash.display.Graphics;
    import flash.display.GraphicsPathCommand;
    import flash.geom.Point;
    
    class GraphicsController {
        private var g:Graphics;
        public var speed:Number;
        public var thickness:Number = 1;
        public var color:Number = 0x3388DD;
        
        private var _degree:Number;
        private var _innerRadius:Number;
        private var _radius:Number;
        
        private var commands:Vector.<int>;
        private var data:Vector.<Number>;
        private var _f:Number;
        private var _f0:Number;
        
        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{
            this._degree = degree;
            this._radius = radius;
            this._innerRadius = innerRadius;
            
            if(degree > 0){
                g.clear();
                g.beginFill(color);
                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,f0:Number = 0):void{
            this.commands = commands.concat();
            this.data = data.concat();
            this._f = f;
            this._f0 = f0;
            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();
            
            if (f < f0){
                var a:Number = f;
                var b:Number = f0;
                f0 = a;
                f = b;
            }
            //全ての曲線の長さの合計をとっておく(それぞれの長さも)
            //長さの算出は今のところ直線距離(改良予定)
            var totalLength:Number = 0;
            var i:int;
            for(i=1;i<commands.length;i++){
                controlPoint = new Point(dat[i*4], dat[i*4+1]);
                endPos = new Point( dat[i*4+2], dat[i*4+3]);
                eachLength.push(Point.distance(startPos,controlPoint) + Point.distance(endPos,controlPoint));
                totalLength += eachLength[i-1];
                startPos = endPos.clone();
            }
            
            var length:Number = 0;
            var trimCtrl:Point;
            var _f:Number;
            var deleted:int = 0;
            if(f0 != 0){
                for(i=0;i<commands.length-1;i++){
                    if( length + eachLength[i] >= f0*totalLength){
                        deleted = i;
                        _f = 1 - (f0*totalLength - length) / eachLength[i];
                                                
                        startPos = new Point(dat[i*4+2], dat[i*4+3]);
                        
                        //コントロールポイント
                        controlPoint = new Point(dat[(i+1)*4], dat[(i+1)*4+1]);
                        endPos = new Point(dat[(i+1)*4+2],dat[(i+1)*4+3]);
                        
                        //分割
                        trimCtrl = Point.interpolate(controlPoint,endPos,_f);
                        trimPos = Point.interpolate(Point.interpolate(startPos,controlPoint,_f),trimCtrl,_f);
                        
                        com.splice(0, i+2);
                        dat.splice(0, (i+2)*4);
                        com.unshift(GraphicsPathCommand.CURVE_TO);
                        com.unshift(GraphicsPathCommand.WIDE_MOVE_TO);
                        dat.unshift(trimCtrl.x, trimCtrl.y, endPos.x, endPos.y);
                        dat.unshift(0, 0, trimPos.x, trimPos.y)
                        break;
                    } else {
                        length += eachLength[i];
                    }
                }    
            }
            
            length = 0;
            if( _f != 1 ){
                for(i=0;i<commands.length;i++){
                    if (length + eachLength[i] >= f*totalLength){
                        //その線分内での割合を算出
                        _f = (f*totalLength - length) / eachLength[i];
                        
                        i -= deleted;
                        startPos = new Point(dat[i*4+2], dat[i*4+3]);
                        
                        i++;
                        //コントロールポイント
                        controlPoint = new Point(dat[i*4], dat[i*4+1]);
                        endPos = new Point(dat[i*4+2], dat[i*4+3]);
                        
                        //分割
                        trimCtrl = Point.interpolate(controlPoint, startPos, _f);
                        trimPos = Point.interpolate(Point.interpolate(endPos,controlPoint,_f),trimCtrl,_f);
                        
                        com.splice(i, com.length-i);
                        com.push(3);
                        dat.splice(i*4,dat.length-i*4);
                        dat.push(trimCtrl.x,trimCtrl.y,trimPos.x,trimPos.y);
                        break;
                    } else{
                        length += eachLength[i];
                    }
                }
            }
            
            g.drawPath( com, dat);
        }
        
        /**
         * getters and setters
         */
        public function set degree(value:Number):void{
            _degree = value;
            //drawPie(degree,radius,innerRadius);
        }
        public function set radius(value:Number):void{
            _radius = value;
            //drawPie(degree,radius,innerRadius);
        }
        public function set innerRadius(value:Number):void{
            _innerRadius = value;
            drawPie(degree,radius,innerRadius);
        }
        public function get degree():Number{ return _degree };
        public function get radius():Number{ return _radius };
        public function get innerRadius():Number{ return _innerRadius };
        
        public function set f(value:Number):void{
            _f = value;
            drawLine(commands,data,_f,_f0);
        }
        public function set f0(value:Number):void{
            _f0 = value;
            drawLine(commands,data,_f,_f0);
        }
        public function get f():Number{ return _f};
        public function get f0():Number{ return _f0 };
    }