補足・追加原稿の最近のブログ記事

「Section08-01 クラス定義の構造」の「クラスメンバーを定義する」(p.245)にサンプルを追加します。このサンプルのポイントは、コンストラクタにおいてクラスプロパティfriendListにインスタンスの参照であるthisを登録することで、作ったインスタンスを管理しているところです。

[:script:]Friend4クラスの定義
package {
  public class Friend4 {
    //クラスプロパティ
    public static var seqNo:uint;
    public static var friendList:Array=new Array();
    //インスタンスプロパティ
    public var no:uint;
    public var name:String;
    public var age:uint;
    //コンストラクタ
    public function Friend4(na:String,ag:uint) {
      no= ++seqNo;
      name=na;
      age=ag;
      //インスタンスのリストに参照を保管する
      friendList.push(this);
    }
    //
    // クラスメソッド
    //
    //平均年齢を求める
    public static function getAgeAverage():Number {
      if (friendList.length==0) {
        return 0;
      } else {
        var ageSum:uint;
        //年齢の合計を出す
        for (var i:int=0; i<friendList.length; i++) {
          var friend:Friend4=friendList[i];
          ageSum+=friend.age;
        }
        //平均を計算する
        var ave:Number=ageSum/friendList.length;
        //小数点2位で四捨五入する
        ave=Math.round(ave*10)/10;
        return ave;
      }
    }
    //最年長を求める
    public static function getOldestProfile():String {
      if (friendList.length==0) {
        return null;
      } else {
        //friendListの複製
        var tmpList:Array=friendList.slice();
        //年齢でソートする
        tmpList.sortOn("age",Array.NUMERIC);
        //最後の人を取り出す
        var oldest:Friend4=tmpList[tmpList.length-1];
        //プロフィールを返す(インスタンスメソッドの実行)
        return oldest.getProfile();
      }
    }
    //
    // インスタンスメソッド
    //
    //プロフィールを返す
    public function getProfile():String {
      var info:String="no."+no+" "+name+"、"+age+"歳です。";
      return info;
    }
  }
}
ファイル一式をダウンロードする
Section14-01 外部イメージファイルを読み込んでフェードインで表示するスクリプト(p.406)のサンプルはLoaderクラスを継承した作りになっているために難しいかもしれません。そこでフレームアクションで実行できるシンプルな例を紹介しておきます。
このスクリプトのポイントは、画像ファイルの読み込み完了イベントEvent.COMPLETEのリスナーをLoaderのインスタンスのcontentLoaderInfoプロパティにaddEventListener()する部分です。(6行目)

[:script:]読み込み完了後にフェードインで表示する
//読み込む画像ファイルを指定する
var url:String = "image/IMG_8171.jpg";
var urlReq:URLRequest = new URLRequest(url);
//ローダーを作る
var photoLoader:Loader=new Loader();
photoLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
//画像を読み込む
photoLoader.load(urlReq);
//画像を表示する
photoLoader.x = 100;
photoLoader.y = 50;
addChild(photoLoader);
//ドロップシャドウを付ける
var dsf:DropShadowFilter=new DropShadowFilter();
dsf.alpha = 0.8;
photoLoader.filters = [dsf];

import fl.transitions.Tween;
import fl.transitions.easing.*;
var tw:Tween;
//フェードインで表示する
function onLoaded(eventObj:Event):void {
	tw = new Tween(photoLoader,"alpha",Regular.easeInOut,0,1,1,true);
}

fadein.jpg
swfを試す

ファイル一式をダウンロードする
Section14-02 テキストファイルの読み込み(p.408)のサンプルはちょっとややこしいので、フレームアクションで実行できるシンプルな例を紹介しておきます。

なお、1〜18行目までは読み込んだテキストデータを表示するためのテキストフィールドを作っています。あらかじめ作ってあるテキストフィールドに表示するならば、この部分は必要ありません。

UTFファイルを読み込む例を示していますが、Shift-JISのファイルを読み込む場合は24行目のSystem.useCodePageの値をtrueに設定します。

[:script:]テキストフィールドを作り、外部テキストファイルを読み込む
import flash.text.TextFieldAutoSize;
//テキストフィールドを作る
var fld:TextField=new TextField();
fld.x = 100;
fld.y = 50;
fld.width = 280;
fld.height = 180;
fld.border = true;
fld.multiline = true;
fld.wordWrap = true;
fld.autoSize = TextFieldAutoSize.LEFT;
addChild(fld);
//書式の設定
var tf:TextFormat = new TextFormat();
tf.size = 18;
tf.color = 0x333333;
fld.defaultTextFormat = tf;

//URLLoaderのインスタンスを作る
var txtloader=new URLLoader();
var urlReq:URLRequest=new URLRequest();
urlReq.url = "./data/sample_utf.txt";
//unicodeならばfalse
System.useCodePage = false;
txtloader.load(urlReq);
//読み完了イベントのリスナーを登録する
txtloader.addEventListener(Event.COMPLETE,completeHandler);
//リスナー関数
function completeHandler(eventObj:Event):void {
	//読み込んだテキストをフィールドに表示する
	fld.text = txtloader.data;
}

ファイル一式をダウンロードする
最初にswfを表示する際の読み込み待ちについて簡単に紹介しましょう。AS2まではframesLoadedプロパティを使って、特定のフレーム、特定のインスタンスが読み込まれたどうか判断して読み込み待ちを行いました。

[:script:]最後まで読み込まれたらtopへ進む。それまではループする。
if (this.framesLoaded == this.totalFrames) {
    gotoAndPlay("top");
}else{
   gotoAndPlay("loop");
}

framesLoadedプロパティを使った方法はAS3でも使えますが、AS3からは次に示すようにloaderInfoのprogressイベントのリスナーになり、bytesLoadedとbytesTotalのプロパティを使うことでダウンロード量を調べることができます。

[:script:]プログレスバーを表示するフレームアクション
stop();
var bar:Sprite = new Sprite();
bar.graphics.beginFill(0x000000);
bar.graphics.drawRect(0,0,1,5);
bar.graphics.endFill();
bar.y=stage.stageHeight/2;
addChild(bar);
loaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
loaderInfo.addEventListener(Event.COMPLETE, completeHandler);

function progressHandler(eventObj:ProgressEvent):void {
	var per:Number = loaderInfo.bytesLoaded/loaderInfo.bytesTotal;
	bar.width = stage.stageWidth*per;
}
function completeHandler(eventObj:Event):void{
		removeChild(bar);
		loaderInfo.removeEventListener(ProgressEvent.PROGRESS, progressHandler);
		loaderInfo.removeEventListener(Event.COMPLETE, completeHandler);
		gotoAndStop("top");
}
swfを試す
1回実行するとブラウザにキャッシュされるので、2回目以降はプログレスバーが表示されない場合があります。

これを見て外部jpegやswfを読み込むLoaderでの処理と同じと思った人も多いはず。そうです。LoaderのcontentLoaderInfoですね。contentLoaderInfoは読み込むコンテンツオブジェクトのloaderInfoの値なんですね。

フォントの英語名はどうすれば調べることができるでしょうか?
実はけっこう簡単です。次のようにフォントを設定したテキストフィールドを選択した状態でコマンドメニューの[ActionScript用にフォント名をコピー]を実行します。あとはテキストエディタにペーストするだけです。
こんなメニューがあったのか!と思った人もいるでしょうけど、あったんですね。(^ ^)/

fontname01.jpg
フォントを指定しているテキストフィールドを選択する。

fontname02.jpg
[ActionScript用にフォント名をコピー]を実行。

fontname03.jpg
ペーストすると英語のフォント名が貼り付けられる。

実はもっと簡単な方法のもあります。環境設定のテキストパネルで[フォント名を英語表記]をチェックします。するとフォント名はすべて英語で表示されます。ただし、先の方法のペースト結果をみるとわかるように、フォント名はスタイルメニューの値(W4など)と組み合わせる必要があります。

fontname04.jpg
環境設定のテキストパネルで[フォント名を英語表記]をチェックする。

fontname05.jpg
フォントメニューが英語のフォント名で表示される。

スクリプトでテキストフィールドmyFldのフォント名を調べたい場合は、次のように実行します。ただし、myFldには何かテキストが入っている必要があります。
var tf:TextFormat = myFld.getTextFormat();
trace(tf.font); // Hiragino Maru Gothic Pro W4
 シンボルにもカスタムクラスを関連付けることができます。この手法は先に出版したAS3入門ノートでは解説していましたが、今回の完全改訂版では割愛した内容です。その内容をここで補足したいと思います。

 シンボルからインスタンスを作る方法は「Section07-01 表示オブジェクトの追加」に説明してあるので、ここが補足箇所の候補になりますが(p.211)、この時点ではクラス定義や継承について学んでいません。
 シンボルとカスタムクラスを関連付ける方法はドキュメントクラスと同じ考え方なので、「Section08-06 ドキュメントクラス」の最後のp.486が適当でしょう。ここに以下の原稿を追加します。

シンボルが継承するクラス 追加原稿 p.486
 ドキュメントクラスと同じようにシンボルにもカスタムクラスを関連付けることができます。シンボルにカスタムクラスを関連付けるには、シンボルのプロパティパネルでリンケージ書き出しの設定を行い、クラスフィールドにカスタムクラスを指定します。

fig 08-06-04.jpg
シンボルのリンケージ書き出し設定で関連付けるクラスを指定します

 たとえば、次のFlowerAクラスをシンボルに関連付けると、このシンボルから作ったインスタンスをステージに追加するだけで回転するようになります。このとき、ムービークリップシンボルに関連付けるカスタムクラスは、必ずMovieClipクラスを継承しなければなりません。
 インスタンスはnew FlowerA()で作ることができますが、普通にライブラリからステージにドロップして作ってもかまいません。

[:script:]シンボルに関連付けるFlowerAクラス
package {
	import flash.display.MovieClip;
	import flash.events.Event;

	public class FlowerA extends MovieClip {
		public function FlowerA() {
			addEventListener(Event.ENTER_FRAME, enterFrameHandler );
		}
		protected function enterFrameHandler(eventObj:Event):void {
			rotation += 3;
		}
	}
}

fig 08-06-05.jpg
インスタンスを作ってステージに追加するだけで回転します。→swfを試す
ファイルをダウンロードするextendSymbol.zip

(section03-01 Arrayクラスの配列から抜粋)

 配列の値を検索したい場合には、すべての値を総当たりでチェックしなければならない場合もありますが、単純に値が含まれているかどうかがわかればよい場合があります。そのような場合にはindexOf()、lastIndexOf()のメソッドが便利です。
 indexOf()は指定した検索開始位置から後ろへ検索して最初に見つかった位置を返します。検索開始位置を省略すると最初から探しします。開始位置をマイナスで指定すると後ろから位置を数えます。検索の結果見つからなかった場合には-1が返ってきます。

[:script:]配列を前から後ろへ検索する
var vlist:Array = new Array("a","x","b","a","x","c");
trace(vlist.indexOf("a",2));//出力:3
trace(vlist.indexOf("a",4));//出力:-1
//開始位置を省略
trace(vlist.indexOf("a"));//出力:0
//開始位置を後ろから数える
trace(vlist.indexOf("x",-3));//出力:4
補足:
2行目:"a"をインデックス番号2、つまり"b"の位置から後ろへ検索します。すると"b"の次の"a"が見つかります。この"a"はインデックス番号3なので3が返ります。
3行目:インデックス番号4の"x"の位置から"a"の検索を開始します。"x"より後ろに"a"はないので-1が返ります。
5行目:配列の先頭から"a"を検索します。先頭の"a"が見つかるので、インデックス番号0が返ります。
7行目:検索開始位置が-3なので、後ろから3個目の"a"から検索を開始します。検索方向は"a"から後ろ方向です。"a"の次の"x"が見つかります。この"x"のインデックス番号は4番です。

 lastIndexOf()は指定した検索開始位置から手前に検索して最初に見つかった位置を返します。検索開始位置を省略すると最後から探します。開始位置をマイナスで指定すると後ろから位置を数えます。検索の結果見つからなかった場合には-1が返ってきます。

[:script:]配列を後ろから前へ検索する
var vlist:Array=new Array("a","x","b","a","x","c");
trace(vlist.lastIndexOf("a",2));//出力:0
trace(vlist.lastIndexOf("a",4));//出力:3
//開始位置を省略
trace(vlist.lastIndexOf("a"));//出力:3
//開始位置を後ろから数える
trace(vlist.lastIndexOf("x",-3));//出力:1
補足:
後ろから検索しても、返ってくる値は前から数えるインデックス番号です。勘違いしやすいので注意してください。
2行目:インデックス番号2、つまり"b"の位置から前方向に"a"を検索します。先頭の"a"が見つかるので、インデックス番号0が返ります。
3行目:インデックス番号4、つまり後ろの"x"の位置から前方向へ"a"を検索します。すぐ左の"a"が見つかるので、インデックス番号3が返ります。
5行目:開始位置を省略すると最後から手前へ検索します。後ろの"a"が見つかるので、インデックス番号3が返ります。後ろから3個目ではなく、"a"のインデックス番号です。
7行目:後ろから3個目の"a"から前方向へ"x"を検索します。前から2個目の"x"が見つかるので、インデックス番号1が返ります。

 次のuniquePush()はnoListに同じ値が入っていなければ値を追加する関数です。引数で渡された値が配列に含まれていないかどうかをindexOf()で検索して確かめ、検索結果が-1のときに値をpush()しています。

[:script:]ユニークな値だけ配列に追加する
function uniquePush(tmplist:Array, v:int):void {
	//値が配列に含まれていないか検索する
	var index:int=tmplist.indexOf(v);
	if (index==-1) {
		//値を追加する
		tmplist.push(v);
	}
}
//配列に値を追加していく
var noList:Array=new Array(1,2,3);
uniquePush(noList,2);
uniquePush(noList,50);
uniquePush(noList,60);
uniquePush(noList,50);
trace(noList);//出力:1,2,3,50,60

 ActionScript 3.0 言語およびコンポーネントリファレンスでLoaderクラスの説明を見ると継承には次のように書いてあります。

継承:Loader→DisplayObjectContainer→InteractiveObject   →DisplayObject→EventDispatcher→Object

 これを見ると確かにLoaderクラスはDisplayObjectContainerクラスを継承しているので、MovieClipやSpriteなどと同じようにaddChild()を使って入れ子の表示オブジェクトを追加できるはずです。しかし実際にはLoaderが表示できるのは読み取り専用のcontantプロパティで参照できる表示オブジェクトだけです。
 その理由はコンポーネントリファレンスの説明の続きに書いてあります。そこには次のように書いてあります。

Loaderクラスの説明

Loader クラスは、継承する次のメソッドをオーバーライドします。これは、Loader オブジェクトが持つことができるのは 1 つの子表示オブジェクト、つまり読み込むオブジェクトに限られているためです。次のメソッドを呼び出すと例外がスローされます。メソッドは、addChild()、addChildAt()、removeChild()、removeChildAt() および setChildIndex() です。読み込まれた表示オブジェクトを削除するには、親の DisplayObjectContainer 子配列から Loader オブジェクトを削除する必要があります。

 p.225の表示リストの図でLoaderを二重枠にしていない理由はそういうわけでした。

fig07-02-06.jpg

(section08-03 クラス継承の補足)

 ※複数のクラスを継承する方法について補足します。p.260のextendsの補足説明になります。

複数のクラスを継承する
 MovieClipクラスはSpriteクラスやDisplayObjectクラスなどの複数のクラスを継承していますが、このように複数のクラスを継承したい場合はどうすればよいのでしょうか。結論から言えば1つのサブクラスは1つのスーパークラスしか指定できません。たとえば、MyClassAとMyClassBの両方を継承したMyClassCを作りたいとき、次のようにスクリプトを書くことはできません。

間違ったスクリプト1
class MyClassC extends MyClassA, MyClassB; 
間違ったスクリプト2
class MyClassC extends MyClassB extends MyClassA; 

 MyClassAとMyClassBの両方を継承したMyClassCを作りたいならば、まず、MyClassAを継承したMyClassBを作り、次にMyClassBを継承したMyClassCを作るという方法をとります。たとえば、次のMyClassCではスーパークラスであるMyClassBのtestB()だけでなく、そのMyClassBのスーパークラスのMyClassAのtestA()も利用できます。
 このように親がさらにその親を継承していくという手法によって結果としてサブクラスが複数のクラスを継承できます。

[:script:]MyClassAクラス
package {
	public class MyClassA {
		public function testA() {
			trace("test A");
		}
	}
}

[:script:]MyClassAクラスを継承しているMyClassBクラス
package {
	public class MyClassB extends MyClassA {
		public function testB() {
			trace("test B");
		}
	}
}

[:script:]MyClassBクラスを継承しているMyClassCクラス
package {
	public class MyClassC extends MyClassB {
		public function testC() {
			testA();//MyClassAから継承しているメソッド
			testB();//MyClassBから継承しているメソッド
		}
	}
}

 なお、インスタンスが特定のクラスを継承しているかどうかはis演算子を使って判断できます。

[:script:]指定のクラスを継承しているかどうか調べる
var mc:MovieClip=new MovieClip();
trace(mc is DisplayObject);//出力:true
trace(mc is EventDispatcher);//出力:true
trace(mc is Number);//出力:false
■この訂正は初版のものです。

p.110 のsplice()の説明が間違っていました。内容を訂正しお詫びします。間違っていたのは、第2引数で指定する値がendIndexではなく、deleteCountである点です。さらに第3引数以降で値を挿入できます。
splice()は次のようなメソッドです。p.108のslice()とスペルが似ているので注意です。また、インデックス番号は0から数えるので、「1番目」とは2個目の値を指しています。番目を「インデックス番号」と読み替えてください。

訂正文:
 抜き取る際に値を複製せずに元の配列から値を削除します。また、値を抜き取った位置に新しい値を代わりに挿入することもできます。これにより、splice()は値を抜き出すだけでなく、配列の値の削除や置換の目的でも利用できます。
 splice()の書式は次のとおりです。第1引数startIndexは抜き取り開始位置のインデックス番号、第2引数のdeleteCountでは抜き取る値の個数を指定します。入れ替える値は第3引数以降にカンマで区切って指定します。

書式:
splice(startIndex:int, deleteCount:uint, ... values):Array

 次の例では配列stockListのインデックス番号1から4個の値を抜き取って新しい配列pickUpListを作成します。元の配列stockListからは抜き取られた値が削除されています。

[:script:]配列のインデックス番号1から4個の値を抜き取る
var stockList:Array = ["a","b","c","d","e","f"];
var pickUpList:Array = stockList.splice(1,4);
//取り出した配列
trace(pickUpList);//出力:b,c,d,e
//元の配列からは値が抜き取られて削除されている
trace(stockList);//出力:a,f
 splice()は第2引数以降を省略できます。splice(3)のように引数を省略するとインデックス番号3から最後までの値を抜き出します。

[:script:]配列のインデックス番号3から最後までの値を抜き出す
var stockList:Array=["a","b","c","d","e","f"];
var pickUpList:Array=stockList.splice(3);
trace(pickUpList);//出力:d,e,f
trace(stockList);//出力:a,b,c
 引数をマイナスにすると末尾から個数を数えて取り出します。次の例は末尾から4個の値を取り出した配列を作ります。元の配列のstockListからは末尾の4個が削除されています。

[:script:]配列の末尾から4個を抜き出す
var stockList:Array=["a","b","c","d","e","f"];
var pickUpList:Array=stockList.splice(-4);
trace(pickUpList);//出力:c,d,e,f
trace(stockList);//出力:a,b

追加サンプル:
値を入れ替えるサンプルがないので、ここに新しいサンプルを追加しましょう!

[:script:]配列のインデックス番号2から3個の値を抜きとり、代わりに"X"、"Y"を挿入する。
var stockList:Array=["a","b","c","d","e","f"];
var pickUpList:Array=stockList.splice(2,3,"X","Y");
trace(pickUpList);//出力:c,d,e
trace(stockList);//出力:a,b,X,Y,f
まったく新しいAS3の世界!
694a.jpg
Adobe Flash CS4
詳細!ActionScript3.0入門ノート[完全改訂版](CD-ROM付)

楽しいActionScript。
新たなる1歩へと踏み出しましょう。
■内容は?→ 目次を見る
■評判は?→ 書評を読む
この本を書いたわけ

このアーカイブについて

このページには、過去に書かれたブログ記事のうち補足・追加原稿カテゴリに属しているものが含まれています。

前のカテゴリは目次です。

次のカテゴリは連載Adobe EDGEです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

あわせて読みたいブログパーツ