Beautifl - Flash Gallery

Thumbnail : [BetweenAS3] Setting Composite Tween Duration
[BetweenAS3] Setting Composite Tween Duration
clockmaker 2009-08-28 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

/**
 * BetweenAS3を使うと、複合Tweenの再生時間も設定できるというデモ
 * 右下のラジオボタンを選択してお試しください。
 * たぶん、他のTweenエンジンだとできなかったことだと思います。
 * 
 * なお、再生時間変更のロジックは次の式で実装できます。
 * 新トウィーン = BetweenAS3.scale(オリジナルトウィーン, 設定したい秒数 / オリジナルトウィーン.duration);
 * trace(新トウィーン.duration); // 設定した秒数の値が出力される
 */
package {
    import com.bit101.components.*
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.net.*
    import flash.system.*;
    import flash.utils.*;
    import org.libspark.betweenas3.*;
    import org.libspark.betweenas3.easing.*;
    import org.libspark.betweenas3.tweens.ITween;
    import org.papervision3d.cameras.*;
    import org.papervision3d.view.*;
    import org.papervision3d.materials.*;
    import org.papervision3d.objects.*;
    import org.papervision3d.objects.primitives.*
    import net.hires.debug.Stats;
    
    [SWF(width = "465", height = "465", frameRate = "60")]
    public class Main extends BasicView {
        
        // 分割数です 5の倍数だと画像が荒れません
        static private const MAX_CELL_W:uint = 20;
        static private const MAX_CELL_H:uint = 15;
        
        private var image:Loader = new Loader();
        public function Main() {
            var context:LoaderContext = new LoaderContext(true);
            image.contentLoaderInfo.addEventListener(Event.COMPLETE, init);
            image.load(new URLRequest("http://farm1.static.flickr.com/50/146026358_13c698d683.jpg"), context);
        }
        
        private function init(e:Event):void {
            stage.quality = StageQuality.MEDIUM;
            viewport.opaqueBackground = 0xFFFFFF;
            
            // 画像を分割キャプチャします
            var bitmap:Bitmap = image.content as Bitmap;
            var bmpDataArr:Array /* type of BitmapData */ = [];
            
            // 二重ループを開始します
            var i:int = 0;
            var j:int = 0;
            for (i = 0; i < MAX_CELL_W; i++ ) {
                for (j = 0; j < MAX_CELL_H; j++ ) {
                    var bmpData:BitmapData = new BitmapData(bitmap.width / MAX_CELL_W, bitmap.height/ MAX_CELL_H, false, 0xFF000000);
                    
                    // 行列を用いてキャプチャする画像の原点をずらします
                    var matrix:Matrix = new Matrix();
                    matrix.translate( - bitmap.width / MAX_CELL_W * i, - bitmap.height / MAX_CELL_H * j);

                    //  行列変換を用いてキャプチャします
                    bmpData.draw(bitmap, matrix);
                    bmpDataArr.push(bmpData);
                }
            }
            
            // 分割平面を作成します
            var wrap:DisplayObject3D = scene.addChild(new DisplayObject3D());
            wrap.x = - bitmap.width / 2;
            wrap.y = - bitmap.height / 2;
            
            // 細切れになった写真の3Dパーツを保存する配列です
            var planeArr:Array /* type of Array */ = [];
            
            for (i = 0; i < MAX_CELL_W; i++ ) {
                planeArr[i] /* type of Plane */ = [];
                for (j = MAX_CELL_H; j > 0 ; j-- ) {
                    var material:BitmapMaterial = new BitmapMaterial(BitmapData(bmpDataArr.shift()));
                    
                    var plane:Plane = new Plane(material, bitmap.width / MAX_CELL_W, bitmap.height / MAX_CELL_H, 1, 1);
                    plane.x = bitmap.width / MAX_CELL_W * i;
                    plane.y = bitmap.height / MAX_CELL_H * j;
                    
                    planeArr[i][j] = wrap.addChild(plane);
                }
            }
            
            var orijinalTween:ITween;
            var currentTween:ITween;
            var tweens:Array = [];
            // 分割平面のモーションを設定します
            for (i = 0; i < planeArr.length; i++ ) {
                for (j = 1; j < planeArr[i].length ; j++ ) {
                    plane = Plane(planeArr[i][j]);
                    var distance:Number = Math.sqrt(i * i + j * j);
                    tweens.push(
                        BetweenAS3.delay(
                            BetweenAS3.tween(plane,
                                {z : 0 },
                                {z : -2000 },
                                1.5,
                                Quintic.easeOut),
                            distance * .086));
                            
                    tweens.push(
                        BetweenAS3.delay(
                            BetweenAS3.tween(plane,
                                { rotationY  : 0 },
                                { rotationY  : 360 },
                                0.75,
                                Quintic.easeOut),
                            distance * .06  + 1.1));
                }
            }
            
            // カメラのモーションを設定します
            tweens.push(
                BetweenAS3.tween(camera,
                    { x:0, y:0, z: -200, focus:100, zoom:2 },
                    { x:400, y:400, z: -1500, focus:90, zoom:1.5 },
                    3.3,
                    Quintic.easeInOut));
                    
            currentTween = orijinalTween = BetweenAS3.parallelTweens(tweens);
            currentTween.play();
            
            // レンダリングを開始します
            startRendering();
            
            // デバッグ
            addChild(new Stats);
            
            // スピード調整バー
            var btn1:RadioButton = new RadioButton( this, 300, 440, "Orijinal", true, onChangeSpeed );
            var btn2:RadioButton = new RadioButton( this, 350, 440, "2.0 sec", false, onChangeSpeed );
            var btn3:RadioButton = new RadioButton( this, 400, 440, "10.0 sec", false, onChangeSpeed );
            var lastBtn:RadioButton = btn1;
            var label:Label = new Label(this, 300, 420, "");
            
            // イベントハンドラ
            function onChangeSpeed(event : Event) : void {
                if(lastBtn != event.currentTarget) {
                    if(lastBtn) lastBtn.selected = false;
                    lastBtn = event. currentTarget as RadioButton;
                    var time:Number;
                    switch(event. currentTarget){
                        case btn1: time = orijinalTween.duration; break;
                        case btn2: time = 2.0; break;
                        case btn3: time = 10.0; break;
                    }
                    currentTween.stop();
                    
                    // ここがデモのポイント
                    currentTween = BetweenAS3.scale(orijinalTween, time / orijinalTween.duration);
                    currentTween.gotoAndPlay(0);
                    
                    var startTime:Number = getTimer();
                    currentTween.onUpdate = currentTween.onComplete = function():void {
                        label.text = "TIME : " + ((getTimer() - startTime) / 1000) + " sec";
                    }
                }
            }
        }
    }
}