JAVAC.JP
HOSHI TETSUYA 星鉄矢
2005/07/25
hossy@javac.jp
http://www.javac.jp
Google
WWW を検索 WWW.JAVAC.JP を検索

6-4 アニメーションを付加する

前述のサンプルではクリックした際の移動の途中フレームがなくて分かりづらい面がありましたので、アニメーションをつけてみましょう。
example
このサンプルでは毎フレームごとに該当エリアのノードを検索しているので、ノード数が多くなると処理が重くなります。ここでは触れませんが、対策としては、アニメーション開始時と終了時の共通ノードのみを選択し、それらに対してアニメーションを付加するという方法があります。

実装に関してですが、ParamControlクラスに開始時データと終了時データのパラメータを保持し、比率を与えて中割りアニメーションとします。
class ParamControl{
    private var old_scale:Number;
    private var old_cx:Number;
    private var old_cy:Number;
    private var new_scale:Number;
    private var new_cx:Number;
    private var new_cy:Number;
    private var rate:Number;
    private var MINSCALE :Number =100;
    private var MAXSCALE :Number =100*64;

    function ParamControl(){
        setCenterPos(0,0);
        setCenterPos(0,0);
        setScale(400);
        setScale(400);
        setRate(1);
    }

    public function setRate(rate:Number):Void{
        this.rate=rate;
    }

    private function setCenterPos(x:Number,y:Number):Void{
        old_cx=new_cx;
        old_cy=new_cy;
        new_cx=x;
        new_cy=y;
    }

    private function getCenterX():Number{
        return new_cx*rate+old_cx*(1-rate);
    }

    private function getCenterY():Number{
        return new_cy*rate+old_cy*(1-rate);
    }

    private function setScale(scale:Number):Void{
        old_scale=new_scale;
        new_scale=scale;
    }

    private function getScale():Number{
        return new_scale*rate+old_scale*(1-rate);
    }

    public function changePos(x:Number,y:Number):Void{
        var s:Number=new_scale;
        setScale(s);
        setCenterPos(x,y);
    }

    public function changePosScaleUp(x:Number,y:Number):Void{
        var s:Number=new_scale;
        s*=2;
        if(s>=MAXSCALE){
            s=MAXSCALE;
        }
        setScale(s);
        setCenterPos(x,y);
    }

    public function changePosScaleDown(x:Number,y:Number):Void{
        var s:Number=new_scale;
        s/=2;
        if(s<=MINSCALE){
            s=MINSCALE;
        }
        setScale(s);
        setCenterPos(x,y);
    }

    public function getScreenX(x:Number):Number{
        return (x-getCenterX())*getScale()/100;
    }

    public function getScreenY(y:Number):Number{
        return (y-getCenterY())*getScale()/100;
    }

    public function getDataX(x:Number):Number{
        return x*100/getScale()+getCenterX();
    }

    public function getDataY(y:Number):Number{
        return y*100/getScale()+getCenterY();
    }
}
また、クリック時にonEnterFrameでスレッドカウントを行うムービークリップを作るように、GraphControlクラスのマウスイベント部分への追加を行います。
import mx.events.EventDispatcher;

class GraphControl{
    private var path:MovieClip;
    private var stageMc:MovieClip;
    private var mouseListener:MovieClip;
    private var runnable:MovieClip;
    private var count:Number;
    private var count_max:Number=10;
    private var dataStorage:GraphDataStorage;
    private var drawing:DrawingControl;
    private var paramControl:ParamControl;
    private var ex:ExXML;
    private var STAGE_MC_DEPTH:Number=100;
    private var MOUSE_MC_DEPTH:Number=200;
    private var RUNNABLE_MC_DEPTH:Number=300;
    private var XMIN:Number=-320;
    private var YMIN:Number=-240;
    private var XMAX:Number=320;
    private var YMAX:Number=240;

    function GraphControl(path:MovieClip){
        this.path=path;
        path.createEmptyMovieClip("stage_mc",STAGE_MC_DEPTH);
        stageMc=path.stage_mc;
        stageMc._x=320;
        stageMc._y=240;
        dataStorage=new GraphDataStorage();
        drawing=new DrawingControl(stageMc);
        paramControl=new ParamControl();
        loadGraphData("GraphData.xml");
    }

    private function loadGraphData(address:String):Void{
        ex=new ExXML();
        EventDispatcher.initialize(ex);
        ex.onLoad=function(){
            var lo:Object=new Object();
            lo.target=this;
            lo.type="onLoadXML";
            this.dispatchEvent(lo);
        };
        ex.addEventListener("onLoadXML",this);
        ex.load(address);
    }

    public function onLoadXML():Void{
        var arr:Array=ex.firstChild.childNodes;
        var pointNodes:Array;
        var lineNodes:Array;
        for(var i:Number=0;i<arr.length;i++){
            var node:XMLNode=XMLNode(arr[i]);
            if(node.nodeName=="pointlist"){
                pointNodes=node.childNodes;
            }else if(node.nodeName=="linelist"){
                lineNodes=node.childNodes;
            }else{
                trace("XMLNode is invalid form.");
            }
        }
        for(var i:Number=0;i<pointNodes.length;i++){
            var node:XMLNode=XMLNode(pointNodes[i]);
            if(node.nodeName=="point"){
                var o:Object=node.attributes;
                var id:String=String(o.id);
                var x:Number=Number(o.x);
                var y:Number=Number(o.y);
                var index:Number=dataStorage.addPoint(id,x,y);
            }else{
                trace("XMLNode is invalid form.");
            }
        }
        for(var i:Number=0;i<lineNodes.length;i++){
            var node:XMLNode=XMLNode(lineNodes[i]);
            if(node.nodeName=="line"){
                var o:Object=node.attributes;
                var id:String=String(o.id);
                var point1:String=String(o.point1);
                var point2:String=String(o.point2);
                var index:Number=dataStorage.addLine(id,point1,point2);
            }else{
                trace("XMLNode is invalid form.");
            }
        }
        dataStorage.addPointIndexToLineLists();
        drawPoints();
        drawLines();
        addMouseHandler();
    }

    private function drawPoints():Void{
        drawing.resetOvals();
        var x1:Number=paramControl.getDataX(XMIN);
        var y1:Number=paramControl.getDataY(YMIN);
        var x2:Number=paramControl.getDataX(XMAX);
        var y2:Number=paramControl.getDataY(YMAX);
        var arr:Array=dataStorage.getAreaPoint(x1,y1,x2,y2);
        for(var i:Number=0;i<arr.length;i++){
            var n:Number=Number(arr[i]);
            var x:Number=paramControl.getScreenX(dataStorage.getPointPosX(n));
            var y:Number=paramControl.getScreenY(dataStorage.getPointPosY(n));
            var size:Number=20;
            drawing.drawOval(x,y,size);
        }
    }

    private function drawLines():Void{
        drawing.resetLines();
        var x1:Number=paramControl.getDataX(XMIN);
        var y1:Number=paramControl.getDataY(YMIN);
        var x2:Number=paramControl.getDataX(XMAX);
        var y2:Number=paramControl.getDataY(YMAX);
        var arr:Array=dataStorage.getAreaLine(x1,y1,x2,y2);
        for(var i:Number=0;i<arr.length;i++){
            var n:Number=Number(arr[i]);
            var index1:Number=dataStorage.getLineIndex1(n);
            var index2:Number=dataStorage.getLineIndex2(n);
            var x1:Number=paramControl.getScreenX(dataStorage.getPointPosX(index1));
            var y1:Number=paramControl.getScreenY(dataStorage.getPointPosY(index1));
            var x2:Number=paramControl.getScreenX(dataStorage.getPointPosX(index2));
            var y2:Number=paramControl.getScreenY(dataStorage.getPointPosY(index2));
            var size:Number=0;
            var color16:Number=0x000000;
            drawing.drawLine(x1,y1,x2,y2,size,color16);
        }
    }

    private function addMouseHandler():Void{
        path.createEmptyMovieClip("mouse_listener",MOUSE_MC_DEPTH);
        mouseListener=path.mouse_listener;
        mouseListener._x=320;
        mouseListener._y=240;
        EventDispatcher.initialize(mouseListener);
        mouseListener.onMouseDown=function(){
            var lo:Object=new Object();
            lo.target=this;
            lo.type="onMouseDownHandler";
            lo.x=this._xmouse;
            lo.y=this._ymouse;
            this.dispatchEvent(lo);
        };
        mouseListener.addEventListener("onMouseDownHandler",this);
    }

    private function removeMouseHandler():Void{
        mouseListener.removeEventListener("onMouseDownHandler",this);
        mouseListener.removeMovieClip();
    }

    private function onMouseDownHandler(eventObj:Object):Void{
        var x:Number=Number(eventObj.x);
        var y:Number=Number(eventObj.y);
        var tx:Number=paramControl.getDataX(x);
        var ty:Number=paramControl.getDataY(y);
        if(Key.isDown(Key.CONTROL)){
            if(Key.isDown(Key.SHIFT)){
                paramControl.changePosScaleDown(tx,ty);
            }else{
                paramControl.changePosScaleUp(tx,ty);
            }
        }else{
            paramControl.changePos(tx,ty);
        }
        startRunnable();
    }

    private function addRunnable():Void{
        path.createEmptyMovieClip("runnable",RUNNABLE_MC_DEPTH);
        runnable=path.runnable;
        EventDispatcher.initialize(runnable);
        runnable.onEnterFrame=function(){
            var lo:Object=new Object();
            lo.target=this;
            lo.type="onRunnableHandler";
            this.dispatchEvent(lo);
        };
        runnable.addEventListener("onRunnableHandler",this);
    }

    private function removeRunnable():Void{
        runnable.removeEventListener("onRunnableHandler",this);
        runnable.removeMovieClip();
    }

    private function onRunnableHandler():Void{
        count++;
        if(count>=count_max){
            count=count_max;
            stopRunnable();
        }
        paramControl.setRate(count/count_max);
        drawPoints();
        drawLines();
    }

    private function startRunnable():Void{
        count=0;
        removeMouseHandler();
        addRunnable();
    }

    private function stopRunnable():Void{
        addMouseHandler();
        removeRunnable();
    }
}
これらの追加で移動の際にアニメーションが付加されました。



BACKTOPNEXT




All Contents Copyright (C) 2005 HOSHI Tetsuya
Home