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

5-6 削除・挿入を行うDataStorage

エッジの一部分再描画においては、そのエッジのムービークリップのリストにおいて、削除・追加が行われ、今までのように単純にArray型の最後尾に追加していく方法では実装できません。方法としては以下のようにObject型を用いること、
private var list:Object=new Object();

function addItem(index:Number,obj:Object):Void{
    list[String(index)]=obj;
}

function deleteItem(index:Number):Void{
    delete(list[String(index)]);
}
Array型でも以下のようにspliceメソッドを用いること、
private var list:Array=new Array();

function addItem(index:Number,obj:Object):Void{
    list.splice(index,0,obj);
}

function deleteItem(index:Number):Void{
    list.splice(index,1);
}
の2通りが考えられます。
ここで注意したいこととして、Arrayクラスのバグとして、Array型のキャストが存在しないことがあります。
ですので、ArrayクラスやObjectクラスを用いて作成した多重配列のDataStorageからArrayの形で要素を出力することはできません。Array型を用いる場合は、Array型に対するアクセスはなるべくDataStorage内に留めて、キャストできる型でDataStorageから出力するようにする必要があります。前ページのGraphDataStorageクラスで2次元配列を保持している際も、Arrayの形で外部に出力することは避けています。
一方でObject型はキャストできるので、この点でObject型を用いたDataStorageは便利です。リスト(連想配列・ハッシュテーブル)の一部をまるごと取り出すことが可能です。
Object型でDataStorageを作成するメリットはこの他ハッシュテーブル(連想配列)として構成できるため、キーによるアクセスがメインとなり、場合によっては、より使い勝手のよいDataStorageになります。また、キーを重複させることで、データの上書きが簡単に行えます。一方で予期しない原因でキーが被った場合上書きされるという危険性があるということでもあるので注意が必要です。
Object型で構成した際のデメリットとしては、まず、リストの要素数(リスト長)を得るためにfor...in...文を回す必要があるということです。
var len:Number=0;
for(var key:String in list){
    len++;
}
return len;
また、for...in...ループは処理が重いので、Object型を用いる場合はその点に関しても注意が必要です。

以下にこの2通りの方法で作成したDataStorageを記します。このプログラムはどちらのDataStorageでも同様に動きます。

Object型を用いた場合
LineMcDataStorage.as
---
class LineMcDataStorage{
    private var lineMcList:Object;

    function LineMcDataStorage(){
        lineMcList=new Object();
    }

    public function addLineMcList(index:Number,mc:MovieClip):Void{
        lineMcList[String(index)]=mc;
    }

    public function removeLineMcList(index:Number):Void{
        var mc:MovieClip=lineMcList[String(index)];
        mc.removeMovieClip();
        delete(lineMcList[String(index)]);
    }
}
Arrayクラスspliceメソッドを用いた場合
LineMcDataStorage.as
---
class LineMcDataStorage{
    private var lineMcList:Array;

    function LineMcDataStorage(){
        lineMcList=new Array();
    }

    public function getLineMcLength():Number{
        return lineMcList.length;
    }

    public function addLineMcList(index:Number,mc:MovieClip):Void{
        lineMcList.splice(index,0,Object(mc));
    }

    public function removeLineMcList(index:Number):Void{
        var mc:MovieClip=MovieClip(lineMcList[index]);
        mc.removeMovieClip();
        lineMcList.splice(index,1);
    }

    public function getLineMc(index:Number):MovieClip{
        return MovieClip(lineMcList[index]);
    }
}
この他、GraphControlクラス、DrawingControlクラスの変更点は以下の通りです。
GraphControl.as
---
import mx.events.EventDispatcher;

class GraphControl{
    private var path:MovieClip;
    private var stageMc:MovieClip;
    private var dataStorage:GraphDataStorage;
    private var drawing:DrawingControl;
    private var ex:ExXML;
    private var STAGE_MC_DEPTH:Number=100;

    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);
        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();
        drawAllLines();
    }

    private function drawPoints():Void{
        var len:Number=dataStorage.getPointListLength();
        for(var i:Number=0;i<len;i++){
            var x:Number=dataStorage.getPointPosX(i);
            var y:Number=dataStorage.getPointPosY(i);
            var size:Number=20;
            var mc:MovieClip=drawing.drawOval(x,y,size);
            mc.setIndex(i);
            mc.setGraphControl(this);
        }
    }

    private function drawAllLines():Void{
        var len:Number=dataStorage.getLineListLength();
        for(var i:Number=0;i<len;i++){
            drawLine(i);
        }
    }

    private function drawLine(index:Number):Void{
        var index1:Number=dataStorage.getLineIndex1(index);
        var index2:Number=dataStorage.getLineIndex2(index);
        var x1:Number=dataStorage.getPointPosX(index1);
        var y1:Number=dataStorage.getPointPosY(index1);
        var x2:Number=dataStorage.getPointPosX(index2);
        var y2:Number=dataStorage.getPointPosY(index2);
        var size:Number=0;
        var color16:Number=0x000000;
        drawing.drawLine(x1,y1,x2,y2,size,color16,index);
    }

    public function refreshLines(index:Number):Void{
        var len:Number=dataStorage.getConnecterLength(index);
        for(var i:Number=0;i<len;i++){
            var lineIndex:Number=dataStorage.getConnecter(index,i);
            drawing.removeLine(lineIndex);
            drawLine(lineIndex);
        }
    }

    public function setPosition(index:Number,x:Number,y:Number):Void{
        dataStorage.setPointPosition(index,x,y);
    }
}

DrawingControl.as
---
class DrawingControl{
    private var path:MovieClip;
    private var ovalBase:MovieClip;
    private var lineBase:MovieClip;
    private var ovalDepth:Number;
    private var lineDepth:Number;
    private var OVAL_BASE_DEPTH:Number=500;
    private var LINE_BASE_DEPTH:Number=300;
    private var OVAL_START_DEPTH:Number=1;
    private var LINE_START_DEPTH:Number=1;
    private var lineMcList:LineMcDataStorage;

    function DrawingControl(path:MovieClip){
        this.path=path;
        path.createEmptyMovieClip("oval_base",OVAL_BASE_DEPTH);
        ovalBase=path.oval_base;
        path.createEmptyMovieClip("line_base",LINE_BASE_DEPTH);
        lineBase=path.line_base;
        ovalDepth=OVAL_START_DEPTH;
        lineDepth=LINE_START_DEPTH;
        lineMcList=new LineMcDataStorage();
    }

    public function drawOval(x:Number,y:Number,size:Number):MovieClip{
        var depth:Number=ovalDepth;
        ovalDepth++;
        var linkage:String="oval";
        var mcname:String="oval"+String(depth);
        ovalBase.attachMovie(linkage,mcname,depth);
        var mc:MovieClip=ovalBase[mcname];
        mc._x=x;
        mc._y=y;
        mc._xscale=size;
        mc._yscale=size;
        return mc;
    }

    public function drawLine(x1:Number,y1:Number,x2:Number,y2:Number
                        ,size:Number,color16:Number,index:Number):Void{
        var depth:Number=lineDepth;
        lineDepth++;
        var mcname:String="line"+depth;
        lineBase.createEmptyMovieClip(mcname,depth);
        var mc:MovieClip=lineBase[mcname];
        mc.lineStyle(size,color16);
        mc.moveTo(x1,y1);
        mc.lineTo(x2,y2);
        lineMcList.addLineMcList(index,mc);
    }

    public function removeLine(index:Number):Void{
        lineMcList.removeLineMcList(index);
    }
}
これらをコンパイルすると以下のように動きます。
example



BACKTOPNEXT




All Contents Copyright (C) 2005 HOSHI Tetsuya
Home