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: SVG Shape Tween

Get Adobe Flash player
by vuja22 12 Dec 2012
/**
 * Copyright vuja22 ( http://wonderfl.net/user/vuja22 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/1CVs
 */

// forked from kjkmr's SVG Shape Tween
package {
    import flash.display.Sprite;
    import flash.display.Shape;
    import flash.events.Event;
    import caurina.transitions.Tweener;
    
    public class Main extends Sprite {
        
        private var _container:Sprite = new Sprite();
        
        private var _from:BezierPath = new BezierPath(<path fill="none" stroke="#000000" d="M220.3,214.998c0,0-1.08-0.067-1.553,0l-1.62-1.351l-0.404,0.876l-0.744,0.203l-0.676,0.811c0,0-5.334,1.756-9.046,1.892c-3.714,0.134-12.09,1.89-14.519,4.185l-0.541-0.404l-0.539,1.078l0.134-1.01l-0.607,0.473c0,0-1.959-11.412-2.43-13.843c-0.475-2.432-3.176-17.354-7.563-21.338c0,0,1.959-5.94,2.565-15.125c0.609-9.18,2.349-18.734,2.349-18.734s-1.958-6.345,0-17.553c1.958-11.209,2.297-13.371,2.297-13.371l-0.339-0.203c0,0,2.904-2.769,3.445-6.212c0.54-3.443-0.203-7.966-1.284-8.845c0,0-1.418,0.271-0.271,1.35c0,0-0.474,2.297,0,3.849c0.473,1.553-0.743,4.66-2.902,5.133c-2.161,0.472-3.309,0.202-1.755,3.577c0,0,0.302,0.546,0.277,1.756c-0.002,0.065-0.005,0.133-0.01,0.203c-0.066,1.351-1.011,0.472-1.011,0.472l0.673,1.35c0,0,0.744,2.973-1.483,8.914c-2.228,5.941-4.053,16.54-1.892,18.701l0.677,1.014c0,0-1.258,7.765-2.214,11.916c-1.32,5.718-4.325,11.725-4.39,15.463c0,0-5.268,3.982-5.472,7.831c-0.202,3.851,0.609,5.943,1.556,7.293c0.93,1.328,2.174,3.566-1.247,5.376c-0.122-0.329-0.251-0.676-0.399-1.042c-1.312,2.828-3.728,4.998-6.255,6.342c-0.263,0.117-0.528,0.231-0.808,0.332c-4.932,1.752-6.483,0.876-6.483,0.876l0.472,1.486c0,0-6.754-0.812-9.451,1.688l-0.203,0.405c0,0-1.622,0.271-2.095,1.551c0,0-0.539,1.624,0.204,2.771l-0.404,0.336c0,0-0.206-1.957-0.542-2.497c0,0,1.351-1.215,0.811-2.702c0,0,1.554,0.137,0.677-2.294c0,0-1.013-2.229-2.163-1.417c0,0-2.633-2.23-4.457,1.55c0,0-7.291-2.023-8.709,4.729c0,0-2.759,1.757,0.275,3.545l0.427,0.452c0,0,1.778,1.099,2.405,2.339c0.063,0.991-0.499,2.016-1.582,2.336c0.696-0.092,1.311-0.427,1.821-0.903c0.012,1.41-0.131,3.035-0.131,3.035s6.014-0.11,6.788-0.387l0.172-0.408c0,0,5.521-4.016,9.149-2.212c0,0,0.173,0.084,0.492,0.021c0.324-0.064,1.27-0.214,1.27-0.214l5.023,2.599c0,0-2.984,0.301-5.605,0.685c-2.602,0.387-6.498,1.255-8.093,1.396c-0.989-0.214-1.996-0.419-2.958-0.331c0.005-0.005,0.202,0.035,0.243,0.018c-2.513,0.657-5.37,1.188-7.725,1.349c1.506,1.366,4.573,1.193,6.372,0.446c0.011,0.025-0.234,0.231-0.213,0.265c1.738,0.194,3.874-0.03,5.497-0.579c4.258-0.026,19.007-0.107,20.852,0.008c0,0-6.074-6.707-7.154-7.788l0.099-0.088c1.429,0.067,3.495,0.266,4.535,0.397c1.761-3.063,0.888-4.07,1.981-4.783c4.774-3.099,7.013-4.913,10.153-8.541c-0.123-0.036-0.233-0.078-0.353-0.119c0.331-0.349,3.938-4.251,4.153-8.202c0,0,8.622,25.185,9.971,29.304c0,0,22.958-8.71,27.888-9.586l2.16,0.944l1.081-0.944l0.403-0.138c0,0,1.756,1.554,0.202,6.145c0,0-0.605,2.027-2.022,2.295c-1.42,0.272-1.622,0.272-1.622,0.272s0.27,1.146,1.891,1.012c0,0,3.171,0.405,3.713-0.608c0.543-1.012-0.068-2.227,0.34-3.982c0.405-1.755,1.281-1.621,1.62-3.917C223.813,215.671,224.217,213.85,220.3,214.998z"/>);
        private var _to:BezierPath = new BezierPath(<path fill="none" stroke="#000000" d="M188.324,400.087c-0.073-41.951-0.824-83.696-2.438-125.559c-7.783-0.426-17.133,7.253-23.861,10.497c-7.873,3.797-17.965,8.819-27.031,7.805c-15.467-1.729-24.332-33.294-27.273-45.413c-3.588-14.785,8.756-37.561,24.372-40.848c0.211,1.092,0.48,1.495,0.231,2.768c-10.091-6.033-17.466-23.676-22.812-33.491c-5.764-10.583-18.172-32.821-9.924-45.094c5.585-8.311,18.78-7.048,27.262-8.344c4.256-0.651,15.688-4.25,19.863-1.51c8.04-12.021,11.047-24.974,21.201-36.111c6.964-7.639,15.68-16.915,27.167-15.407c8.352,1.096,13.101,11.518,17.978,17.88c4.139,5.4,20.728,23.333,15.585,31.9c-0.689-10.746,25.26-17.366,32.738-18.536c19.253-3.012,44.501,2.573,50.229,23.55c6.092,22.313,4.264,64.883-26.637,67.638c-3.35,0.299-11.462,0.491-9.632-5.535c2.81-9.248,34.339,14.391,36.698,16.236c15.071,11.789,38.446,36.807,21.668,56.506c-9.763,11.461-38.082,26.517-53.532,17.935c-2.376-1.32-4.147-1.99-2.555-4.209c11.77,4.685,14.909,33.047,10.429,42.996c-3.555,7.895-13.639,8.708-21.31,9.044c-13.537,0.593-22.417-6.477-32.581-14.515c-8.529-6.746-20.6-12.772-21.771-24.303c-0.187-1.835-0.566-3.722-0.59-5.55c-5.118,29.655-2.299,61.414-2.299,91.38c0,10.231,0,17.971,0,28.202"/>);
        
        private var _motion:PathMotion = new PathMotion( _container.graphics, _from, _to );
        
        public function Main() {
            
            stage.align = "LT";
            stage.scaleMode = "noScale";
            addChild( _container );
            
            Tweener.addTween( _motion, { position:1, time:1, delay:1, transition:"easeInOutCubic", onComplete:_reverse } );
        }
        
        private function _reverse():void {
            _motion.reverse();
            Tweener.addTween( _motion, { position:1, time:1, delay:0, transition:"easeInOutCubic", onComplete:_reverse } );
        }
        
    }
}

    
    /*--------------------------------------------------
    * 3次ベジェ曲線のアンカーポイントのデータ
    * jp.kimulabo.display.bezier.Anchor
    --------------------------------------------------*/
    
    class Anchor {
        
        /*--------------------------------------------------
        * インスタンス変数
        --------------------------------------------------*/
        public var x:Number;        // x座標
        public var y:Number;        // y座標
        public var prevX:Number;    // 前のコントロールポイントのx座標
        public var prevY:Number;    // 前のコントロールポイントのy座標
        public var nextX:Number;    // 次のコントロールポイントのx座標
        public var nextY:Number;    // 次のコントロールポイントのy座標
        
        /*--------------------------------------------------
        * コンストラクタ
        --------------------------------------------------*/
        public function Anchor( i_x:Number = 0, i_y:Number = 0, i_prevX:Number = NaN, i_prevY:Number = NaN, i_nextX:Number = NaN, i_nextY:Number = NaN ) {
            x = i_x;
            y = i_y;
            prevX = i_prevX || x;
            prevY = i_prevY || y;
            nextX = i_nextX || x;
            nextY = i_nextY || y;
        }
        
        /*--------------------------------------------------
        * toString()
        --------------------------------------------------*/
        public function toString():String {
            return "Anchor{ x:"+x+", y:"+y+", prevX:"+prevX+", prevY:"+prevY+", nextX:"+nextX+", nextY:"+nextY+" }";
        }
        
        /*--------------------------------------------------
        * clone()
        --------------------------------------------------*/
        public function clone():Anchor {
            return new Anchor( x, y, prevX, prevY, nextX, nextY );
        }
    }





    
    import flash.display.Graphics;
    import flash.geom.Point;
    
    /*--------------------------------------------------
    * 3次ベジェ曲線のパスのデータ
    * jp.kimulabo.display.bezier.BezierPath
    --------------------------------------------------*/
    
    class BezierPath {
        
        /*--------------------------------------------------
        * 定数
        --------------------------------------------------*/
        public static const DIVISION:uint = 8;
        public static const DATA_REG:RegExp = /[MmLlCcHhVvSs][0-9,.-]+/;
        
        /*--------------------------------------------------
        * インスタンス変数
        --------------------------------------------------*/
        public var anchors:Array = [];
        public var random:Number = 2;
        
        /*--------------------------------------------------
        * コンストラクタ
        --------------------------------------------------*/
        public function BezierPath( ... args ) {
            if ( args[0] is XML ) parseSVG( args[0] );
            else push.apply( this, args );
        }
        
        /*--------------------------------------------------
        * アンカーポイントを最後に追加
        --------------------------------------------------*/
        public function push( ... args ):void {
            var i:uint, l:uint = args.length;
            for ( i=0; i<l; i++ ) {
                if ( args[i] is Anchor ) {
                    anchors.push( args[i] );
                } else if ( args[i] is Array ) {
                    push.apply( this, args[i] );
                } else {
                    throw("Invalid Argument ( "+ args[i] + " )");
                }
            }
        }
        
        /*--------------------------------------------------
        * 最後のアンカーポイントを削除
        --------------------------------------------------*/
        public function pop():Anchor {
            var a:Anchor = anchors.pop();
            return a;
        }
        
        /*--------------------------------------------------
        * 特定のアンカーポイントの前にアンカーポイントを追加
        --------------------------------------------------*/
        public function before( i_anchor:Anchor, ... args ):void {
            var i:uint, index:int = -1, l:uint = anchors.length;
            for ( i=0; i<l; i++ ) {
                if ( anchors[i] == i_anchor ) {
                    index = i;
                    break;
                }
            }
            
            if ( index < 0 ) return;
            
            var b:Array = anchors.splice( 0, index );
            l = args.length;
            for ( i=0; i<l; i++ ) {
                if ( args[i] is Anchor ) b.push( args[i] );
                else if ( args[i] is Array ) b = b.concat( args[i] );
                else throw("Invalid Argument ( "+args[i]+" )");
            }
            anchors = b.concat( anchors );
            
        }
        
        /*--------------------------------------------------
        * アンカーポイントの数
        --------------------------------------------------*/
        public function get length():uint { return anchors.length; }
        public function set length( i_value:uint ):void {
            while ( anchors.length < i_value ) anchors.push( anchors[ anchors.length - 1].clone() );
        }
        
        /*--------------------------------------------------
        * 特定のアンカーポイントの後にアンカーポイントを追加
        --------------------------------------------------*/
        public function after( i_anchor:Anchor, ... args ):void {
            var i:uint, index:int = -1, l:uint = anchors.length;
            for ( i=0; i<l; i++ ) {
                if ( anchors[i] == i_anchor ) {
                    index = i;
                    break;
                }
            }
            
            if ( index < 0 ) return;
            var b:Array = anchors.splice( 0, index + 1 );
            l = args.length;
            for ( i=0; i<l; i++ ) {
                if ( args[i] is Anchor ) b.push( args[i] );
                else if ( args[i] is Array ) b = b.concat( args[i] );
                else throw("Invalid Argument ( "+args[i]+" )");
            }
            anchors = b.concat( anchors );
        }
        
        /*--------------------------------------------------
        * 複製
        --------------------------------------------------*/
        public function clone():BezierPath {
            var i:uint, l:uint = anchors.length;
            var a:Array = [];
            for ( i=0; i<l; i++ ) a.push( anchors[i].clone() );
            return new BezierPath( a );
        }
        
        /*--------------------------------------------------
        * SVGをパース
        --------------------------------------------------*/
        public function parseSVG( i_xml:XML ):void {
            var d:String = i_xml.@d;
            var pt:Point = new Point();
            var px:Number, py:Number, nx:Number, ny:Number;
            var s:int, m:String, t:String, tt:String, n:Array;
            var prev:Anchor;
            s = d.search( DATA_REG );
            if ( s < 0 ) return;
            anchors = [];
            while( s >= 0 ) {
                m = d.match( DATA_REG )[0];
                t = m.substr(0,1);
                tt = m.substr(1);
                while( tt.match(/([0-9])-/) ) tt = tt.replace(/([0-9])-/,"$1,-");
                n = tt.split(",");
                switch( t ) {
                    /* 移動 */
                    case "m":
                        pt.x += parseFloat(n[0]);
                        pt.y += parseFloat(n[1]);
                        push( new Anchor( pt.x, pt.y ) );
                        break;
                    case "M":
                        pt.x = parseFloat(n[0]);
                        pt.y = parseFloat(n[1]);
                        push( new Anchor( pt.x, pt.y ) );
                        break;
                    
                    /* 水平線 */
                    case "h":
                        pt.x += parseFloat(n[0]);
                        push( new Anchor( pt.x, pt.y ) );
                        break;
                    case "H":
                        pt.x = parseFloat(n[0]);
                        push( new Anchor( pt.x, pt.y ) );
                        break;
                    
                    /* 垂直線 */
                    case "v":
                        pt.y += parseFloat(n[0]);
                        push( new Anchor( pt.x, pt.y ) );
                        break;
                    case "V":
                        pt.y = parseFloat(n[0]);
                        push( new Anchor( pt.x, pt.y ) );
                        break;
                    
                    /* 直線 */
                    case "l":
                        pt.x += parseFloat(n[0]);
                        pt.y += parseFloat(n[1]);
                        push( new Anchor( pt.x, pt.y ) );
                        break;
                    case "L":
                        pt.x = parseFloat(n[0]);
                        pt.y = parseFloat(n[1]);
                        push( new Anchor( pt.x, pt.y ) );
                        break;
                    
                    /* 三次ベジェ */
                    case "c":
                        nx = pt.x + parseFloat(n[0]);
                        ny = pt.y + parseFloat(n[1]);
                        px = pt.x + parseFloat(n[2]);
                        py = pt.y + parseFloat(n[3]);
                        pt.x += parseFloat(n[4]);
                        pt.y += parseFloat(n[5]);
                        if ( anchors.length ) {
                            prev = anchors[anchors.length - 1];
                            prev.nextX = nx;
                            prev.nextY = ny;
                        }
                        push( new Anchor( pt.x, pt.y, px, py ) );
                        break;
                    case "C":
                        nx = parseFloat(n[0]);
                        ny = parseFloat(n[1]);
                        px = parseFloat(n[2]);
                        py = parseFloat(n[3]);
                        pt.x += parseFloat(n[4]);
                        pt.y += parseFloat(n[5]);
                        if ( anchors.length ) {
                            prev = anchors[anchors.length - 1];
                            prev.nextX = nx;
                            prev.nextY = ny;
                        }
                        push( new Anchor( pt.x, pt.y, px, py ) );
                        break;
                        
                    /* 省略型滑三次ベジェ  */
                    case "s":
                        px = pt.x + parseFloat(n[0]);
                        py = pt.y + parseFloat(n[1]);
                        pt.x += parseFloat(n[2]);
                        pt.y += parseFloat(n[3]);
                        if ( anchors.length ) {
                            prev = anchors[anchors.length - 1];
                            prev.nextX = isNaN(prev.prevX) ? prev.x : prev.x + ( prev.x - prev.prevX );
                            prev.nextY = isNaN(prev.prevY) ? prev.y : prev.y + ( prev.y - prev.prevY );
                        }
                        push( new Anchor( pt.x, pt.y, px, py ) );
                        break;
                    case "S":
                        nx = parseFloat(n[0]);
                        ny = parseFloat(n[1]);
                        px = parseFloat(n[2]);
                        py = parseFloat(n[3]);
                        pt.x += parseFloat(n[4]);
                        pt.y += parseFloat(n[5]);
                        if ( anchors.length ) {
                            prev = anchors[anchors.length - 1];
                            prev.nextX = isNaN(prev.prevX) ? prev.x : prev.x + ( prev.x - prev.prevX );
                            prev.nextY = isNaN(prev.prevY) ? prev.y : prev.y + ( prev.y - prev.prevY );
                        }
                        push( new Anchor( pt.x, pt.y, px, py ) );
                        break;
                    default:
                        trace(t);
                        break;
                }
                //
                d = d.substr( m.length );
                s = d.search( DATA_REG );
            }

        }
        
        /*--------------------------------------------------
        * Graphics描画
        * 分割して3次ベジェを2次ベジェに変換して描画
        --------------------------------------------------*/
        public function redraw( i_graphics:Graphics ):void {
            i_graphics.clear();
            draw( i_graphics );
        }
        
        public function draw( i_graphics:Graphics ):void {
            //初期化
            if ( !anchors.length ) return;
            
            var i:uint;
            var l:uint = anchors.length - 1;
            var t:Number;
            var offset:Number = 1 / DIVISION;
            var pt1:Point;
            var pt2:Point;
            var pt3:Point;
            var sa:Anchor, ea:Anchor;
            var s:Boolean, e:Boolean;
            var b:BezierSegment;
            
            i_graphics.lineStyle( 1, 0 );
            i_graphics.moveTo( anchors[0].x,  anchors[0].y );
            for ( i=0; i<l; i++ ) {
                sa = anchors[i];
                ea = anchors[i+1];
                if ( sa.x == ea.x && sa.y == ea.y ) continue;
                //コントロールポイントの有無
                s = ( !isNaN( sa.nextX ) && !isNaN( sa.nextY ) ) as Boolean;
                e = ( !isNaN( ea.prevX ) && !isNaN( ea.prevY ) ) as Boolean;
                if ( s && e ) {
                    //3次ベジェを分割して近似2次ベジェに変換
                    b = new BezierSegment(
                        new Point( sa.x, sa.y ),
                        new Point( sa.nextX || 0, sa.nextY || 0 ), 
                        new Point( ea.prevX || 0, ea.prevY || 0 ), 
                        new Point( ea.x, ea.y )
                    );
                    t = 0;
                    while ( t < 1.0 - offset ) {
                        pt1 = b.getValue(t);
                        t += offset;
                        pt2 = b.getValue(t);
                        t += offset;
                        pt3 = b.getValue(t);
                        
                        pt2 = new Point(
                            pt2.x * 2 - ( pt1.x + pt3.x ) * 0.5,
                            pt2.y * 2 - ( pt1.y + pt3.y ) * 0.5
                        );
                        if ( random != 0 ) {
                            pt2.x += Math.random() * random - random * 0.5;
                            pt2.y += Math.random() * random - random * 0.5;
                            pt3.x += Math.random() * random - random * 0.5;
                            pt3.y += Math.random() * random - random * 0.5;
                        }
                        i_graphics.curveTo( pt2.x, pt2.y, pt3.x, pt3.y );
                    }
                } else {
                    //直線
                    i_graphics.lineTo( ea.x, ea.y );
                }
            }
        }
        
    }



    
    import flash.display.Graphics;
    import flash.geom.Point;
    
    /*--------------------------------------------------
    * 3次ベジェ曲線のパスのデータのシェイプトゥイーン
    * jp.kimulabo.display.bezier.PathMotion
    --------------------------------------------------*/
    
    class PathMotion {
        
        /*--------------------------------------------------
        * 定数
        --------------------------------------------------*/
        
        /*--------------------------------------------------
        * インスタンス変数
        --------------------------------------------------*/
        private var _graphics:Graphics;
        private var _path:BezierPath;
        private var _from:BezierPath;
        private var _to:BezierPath;
        private var _position:Number = 0;
        
        /*--------------------------------------------------
        * コンストラクタ
        --------------------------------------------------*/
        public function PathMotion( i_graphics:Graphics, i_from:BezierPath = null, i_to:BezierPath = null ) {
            _graphics = i_graphics;
            from = i_from;
            to = i_to;
        }
        
        /*--------------------------------------------------
        * getter & setter for from / to
        --------------------------------------------------*/
        public function get from():BezierPath { return _from; }
        public function set from( i_value:BezierPath ):void {
            _from = i_value;
            if ( _from ) _path = _from.clone();
            adjustLength();
            position = _position;
        }
        
        public function get to():BezierPath { return _to; }
        public function set to( i_value:BezierPath ):void {
            _to = i_value;
            adjustLength();
            position = _position;
        }
        
        public function adjustLength():void {
            if ( !_from || !_to || !_path ) return;
            _from.length = _to.length;
            _to.length = _from.length;
            _path.length = _from.length;
        }
        
        /*--------------------------------------------------
        * reverse();
        --------------------------------------------------*/
        public function reverse():void {
            var f:BezierPath = _from;
            _from = _to;
            _to = f;
            position = 1-_position;
        }
        
        /*--------------------------------------------------
        * getter & setter for position
        --------------------------------------------------*/
        public function get position():Number { return _position; }
        public function set position( i_value:Number ):void {
            if ( !_from || !_to ) return;
            _position = i_value;
            var i:uint, l:uint = _path.length;
            var a:Anchor, from:Anchor, to:Anchor;
            
            for ( i=0; i<l; i++ ) {
                a = _path.anchors[i];
                from = _from.anchors[i];
                to = _to.anchors[i];
                a.x = from.x + ( to.x - from.x ) * _position;
                a.y = from.y + ( to.y - from.y ) * _position;
                a.prevX = from.prevX + ( to.prevX - from.prevX ) * _position;
                a.prevY = from.prevY + ( to.prevY - from.prevY ) * _position;
                a.nextX = from.nextX + ( to.nextX - from.nextX ) * _position;
                a.nextY = from.nextY + ( to.nextY - from.nextY ) * _position;
            }
            _path.redraw( _graphics );
        }
        
        
    }


    /*--------------------------------------------------
    * BezierSegment
    *
    * wonderflに fl.motion.BezierSegment がないから、@nanlow さんのを拝借してちょっと修正
    * http://wonderfl.net/c/dHyt
    *
    --------------------------------------------------*/

    class BezierSegment {
        private var _anchor0:Point;
        private var _anchor1:Point;
        private var _controll0:Point;
        private var _controll1:Point;
        public function BezierSegment(anchor0:Point, controll0:Point, controll1:Point, anchor1:Point) {
            _anchor0 = anchor0;
            _anchor1 = anchor1;
            _controll0 = controll0;
            _controll1 = controll1;
        }
        public function getValue(per:Number):Point {
            if (per < 0 || 1 < per) {
                throw new Error(' 0≦per≦1でお願いしますm(_ _;)m');
            }
            var p:Number = 1 - per;
            return new Point(p * p * p * _anchor0.x + 3 * p * p * per * _controll0.x + 3 * p * per * per * _controll1.x + per * per * per * _anchor1.x,p * p * p * _anchor0.y + 3 * p * p * per * _controll0.y + 3 * p * per * per * _controll1.y + per * per * per * _anchor1.y);
        }
    }