Adobe EDGEで全5回の連載を開始しました。
『大重美幸のこれ見落としてませんか? ActionScript 3.0』

内容はもちろんActionScript3.0。知ってそうで知らない。今さら人には聞きづらいといったことを取り上げていく予定です。第1回は『あなたが思う以上に自由自在な「Button コンポーネント」』です。
Adobe EDGEで全5回の連載を開始しました。
『大重美幸のこれ見落としてませんか? ActionScript 3.0』

内容はもちろんActionScript3.0。知ってそうで知らない。今さら人には聞きづらいといったことを取り上げていく予定です。第1回は『あなたが思う以上に自由自在な「Button コンポーネント」』です。
//4個のmcに同じ機能のイベントリスナーを追加する
ball1_mc.addEventListener(MouseEvent.CLICK, stepRotation1);
ball2_mc.addEventListener(MouseEvent.CLICK, stepRotation2);
ball3_mc.addEventListener(MouseEvent.CLICK, stepRotation3);
ball4_mc.addEventListener(MouseEvent.CLICK, stepRotation4);
//ball1_mcを回転させる
function stepRotation1(eventObj:MouseEvent):void {
ball1_mc.rotation+=10;
}
//ball2_mcを回転させる
function stepRotation2(eventObj:MouseEvent):void {
ball2_mc.rotation+=10;
}
//ball3_mcを回転させる
function stepRotation3(eventObj:MouseEvent):void {
ball3_mc.rotation+=10;
}
//ball4_mcを回転させる
function stepRotation4(eventObj:MouseEvent):void {
ball4_mc.rotation+=10;
}
//4個のmcに同じイベントリスナーを追加する
ball1_mc.addEventListener(MouseEvent.CLICK, stepRotation);
ball2_mc.addEventListener(MouseEvent.CLICK, stepRotation);
ball3_mc.addEventListener(MouseEvent.CLICK, stepRotation);
ball4_mc.addEventListener(MouseEvent.CLICK, stepRotation);
//ターゲットを回転させる
function stepRotation(eventObj:MouseEvent):void {
eventObj.target.rotation+=10;
}
//4個のmcに同じイベントリスナーを追加する
ball1_mc.addEventListener(MouseEvent.CLICK, stepRotation);
ball2_mc.addEventListener(MouseEvent.CLICK, stepRotation);
ball3_mc.addEventListener(MouseEvent.CLICK, stepRotation);
ball4_mc.addEventListener(MouseEvent.CLICK, stepRotation);
//ターゲットを回転させる
function stepRotation(eventObj:MouseEvent):void {
//targetの値をMovieClipクラスにキャストする
var ball_mc:MovieClip=eventObj.target as MovieClip;
ball_mc.rotation+=10;
}
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;
}
}
}
//同じイベントに同じリスナー関数を重ねて追加する
a_mc.addEventListener(Event.ENTER_FRAME, stepRotationA);
a_mc.addEventListener(Event.ENTER_FRAME, stepRotationA);
a_mc.addEventListener(Event.ENTER_FRAME, stepRotationA);
a_mc.addEventListener(Event.ENTER_FRAME, stepRotationA);
//b_mcには1度しか追加しない
b_mc.addEventListener(Event.ENTER_FRAME, stepRotationB);
//回転させる
function stepRotationA(eventObj:Event):void {
a_mc.rotation+=2;
}
function stepRotationB(eventObj:Event):void {
b_mc.rotation+=2;
}
//stepZoomで比率を変化させるための角度
var degree:int;
//同じイベントに別のリスナー関数を重ねて追加する
f_mc.addEventListener(Event.ENTER_FRAME, stepRotation);
f_mc.addEventListener(Event.ENTER_FRAME, stepZoom);
//回転させる
function stepRotation(eventObj:Event):void {
f_mc.rotation+=2;
}
//伸縮とアルファ変更
function stepZoom(eventObj:Event):void {
degree=(degree+2)%360;
//回転角度で比率を変える
var ratio:Number=Math.abs(Math.sin(degree*Math.PI/180));
//伸縮
f_mc.scaleX=f_mc.scaleY=1+9*ratio;
//アルファ変更
f_mc.alpha=Math.max(0.02,1-ratio);
}
//クリックで回転を開始するようにする
box_mc.addEventListener(MouseEvent.CLICK, startRotation);
//回転を始めるリスナー関数
function startRotation(eventObj:MouseEvent):void {
//フレーム再生で回転するようにする
box_mc.addEventListener(Event.ENTER_FRAME, stepRotation);
//クリックで回転を停止するようにする
box_mc.removeEventListener(MouseEvent.CLICK, startRotation);
box_mc.addEventListener(MouseEvent.CLICK, stopRotation);
}
//回転を止めるリスナー関数
function stopRotation(eventObj:MouseEvent):void {
//回転を止める
box_mc.removeEventListener(Event.ENTER_FRAME, stepRotation);
//クリックで回転を開始するようにする
box_mc.addEventListener(MouseEvent.CLICK, startRotation);
box_mc.removeEventListener(MouseEvent.CLICK, stopRotation);
}
//フレーム再生で実行されるリスナー関数
function stepRotation(eventObj:Event):void {
//box_mcを回転させる
box_mc.rotation+=2;
}
→swfを試す
イベントターゲット.removeEventListener(イベントタイプ, リスナー関数);
box_mc.removeEventListener(Event.ENTER_FRAME, stepRotation);
//イベントリスナーを登録する
box_mc.addEventListener(Event.ENTER_FRAME, stepRotation);
box_mc.addEventListener(MouseEvent.CLICK, stopRotation);
//フレーム再生で実行されるリスナー関数
function stepRotation(eventObj:Event):void {
//box_mcを回転させる
box_mc.rotation +=2;
}
//クリックで回転を止めるリスナー関数
function stopRotation(eventObj:MouseEvent):void {
//イベントリスナーを取り除く
box_mc.removeEventListener(Event.ENTER_FRAME, stepRotation);
}
→swfを試す
box_mc.addEventListener(Event.ENTER_FRAME, stepRotation);
//フレーム再生で実行されるリスナー関数
function stepRotation(eventObj:Event):void {
//box_mcを回転させる
box_mc.rotation += 2;
}
なお、Event.ENTER_FRAMEはフレームの移動に合わせて発生するイベントですが、フレームが1フレームしかない場合やstop()でフレーム移動を停止している場合にもフレームレートに合わせて継続的にイベントが発生します。
1.どこで
2.何が起きたら
3.どうする
1.イベントターゲット ・・・・ イベントが発生するオブジェクト
2.イベントタイプ ・・・・ 発生するイベントの種類
3.リスナー関数 ・・・・ イベント発生で実行する関数
1.イベントターゲット ・・・・ box_mc
2.イベントタイプ ・・・・ クリック
3.リスナー関数 ・・・・ test()
イベントターゲット.addEventListener(イベントタイプ, リスナー関数);[:note:] addEventListener()には引数がまだありますが、ここでは省略しています。
box_mc.addEventListener(MouseEvent.CLICK, test);
//クリックで実行されるリスナー関数
function test(eventObj:MouseEvent):void {
trace("test OK");
}
そこで、test()でbox_mcの現在の回転角度つまりbox_mc.rotationに45度を加算すれば、box_mcをクリックするたびにbox_mcが45度回転するようになります。
box_mc.addEventListener(MouseEvent.CLICK, test);
//クリックで実行されるリスナー関数
function test(eventObj:MouseEvent):void {
//box_mcを45度回転させる
box_mc.rotation += 45;
}
var vlist:Array=["青森","千葉","京都","宮崎"]; vlist.reverse(); trace(vlist);//出力:宮崎,京都,千葉,青森
var colors:Array=["black","white","yellow"]; colors_fld.text=colors.toString();
var colors:Array=["black","white","yellow"]; colors_fld.text="色は「"+colors+"」です。";
var colors:Array=["黒","白","赤"];
var msg:String=colors.join("または");
trace(msg);//出力:黒または白または赤
区切りを""にすれば、配列の値を1つのストリングに連結できます。
var colors:Array=["黒","白","赤"];
var msg:String=colors.join("");
trace(msg);//出力:黒白赤
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番です。
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が返ります。
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
var alist:Array=new Array("a","b","c");
var blist:Array=new Array("m","n");
var clist:Array=new Array("x","y","z");
var newlist:Array=alist.concat(blist,clist);
trace(newlist);//出力:a,b,c,m,n,x,y,z
加茂君の初めての本が出版になりました。監修という形でお手伝いしましたが、彼のがんばりには脱帽です。その内容は・・・
最初にコンパイルエラー一覧、コンパイラ警告一覧、ランタイムエラー一覧が29ページあって、そこにはコード番号順にメッセージ本文が日本語と英語でリストになっています。このリストはそのままページインデックスの役目も果たします。
第1章「エラーの基礎知識」はその後です。エラーの基礎知識って?
個々のエラーの説明は続く第2章からです。第2章「コンパイルエラー」第3章「コンパイラ警告」第4章「ランタイムエラー」。どの章も結局エラーについてです。
そうそう、付録もあります。「付録A AS2からの移行」AS2からAS3への移行への変更点です。それが25ページの表になっています。これを守らないとAS2からAS3への移植でエラー続出です。
この本にはエラーメッセージのことしか書いてありません。それなのに375ページもあります。エラーはそんなにあるのか?これは罠なのか?

ActionScript 3.0 エラーアーカイブス
コンパイルエラー・コンパイラ警告・ランタイムエラーの解法
加茂雄亮著/大重美幸監修
→■目次
■萌え本です。こんな本をいったい誰が買うのだろう?
プログラム開発は、たとえ数行のスクリプトであってもエラーとの戦いです。では、プログラム開発者はエラーが嫌いかと言うと実はそうでもなくて、エラーを取り除くデバッグ作業が結構好き、楽しいという人は少なくないようです。むしろ、デバッグ作業を楽しめるようでなければプログラマに向いてないのかもしれません。デバッグ作業はプログラムと対話している楽しさがあり、エラーというボケにエラーメッセージという鋭いツッコミが入るという面白さじゃないですか?
・・・・
効率よくエラーを出し、エラーを潰す。そういった開発スキルを高めるには、出会ったエラーメッセージを漫然とながめスルーするのではなく、エラーメッセージが伝える意味を理解することが何よりも大事なのです。「エラーメッセージを解説しよう」という本書は、その意味において大きな意義があります。
Q.エラーが出るとヘコむ?
A.楽しいです。
(推薦文より抜粋)
var alist:Array=[1,2,3];
//blistにalistを代入する
var blist:Array=alist;
alist.push("x");//alistに"x"を追加
blist.push("y");//blistに"y"を追加
//どちらも同じ値になっている
trace(alist);//出力:1,2,3,x,y
trace(blist);//出力:1,2,3,x,y
配列を複製したい場合にはslice()が利用できます。slice()の引数を省略するとslice(0)を実行した場合と同じになり、配列のすべての値を複製した新しい配列を作ることができます。
var alist:Array=[1,2,3];
//blistにalistを複製して代入する
var blist:Array=alist.slice();
alist.push("x");//alistに"x"を追加
blist.push("y");//blistに"y"を追加
//alistとblistは個別の配列になっている
trace(alist);//出力:1,2,3,x
trace(blist);//出力:1,2,3,y
■この訂正は初版のものです。補足の新規追加原稿も含んでいます。
p.37 本文下から3行目
誤:heikin3wを変数myTest
正:heikin3を変数myTest
p.52 本文2行目(言い回しの修正)
誤:次のいくつか代表的な
正:次にいくつかの代表的な
p.54 「関数の引数の値渡しと参照渡し」の1行目(言い回しの修正)
誤:プリミティブ型であるかリファレンス型にも
正:プリミティブ型なのかリファレンス型なのかにも
p.55 欄外に[:note:]を補足追加します。
[:note:]配列を複製する(p.109)
p.68 スクリプト 「caseの値を式で指定した場合」の行番号6と9
誤:6 case (a>=5 && a<=10) :
正:6 case (a>=5 && a<10) :
誤:9 case (a>10) :
正:9 case (a>=10) :
p.106 本文の下から5行目(言い回しの修正)
誤:undefinedの値になり
正:undefinedが追加され
p.107 本文5行目
誤:["red","yellow","black"]の配列になります。
正:["red","yellow","green","black"]の配列になります。
p.210 最終行に本文とスクリプトを補足追加
また、あるクラスがDisplayObjectクラスを継承しているかどうかは、is演算子でもチェックできます。
[:script:]MovieClipクラスがDisplayObjectクラスを継承しているか調べる
1 var mc:MovieClip=new MovieClip();
2 trace(mc is DisplayObject);//出力:true
p.409 スクリプトの39行目コメント文
誤:読み込み完了イベントの配信
正:読み込みエラーイベントの配信
var allList:Array=["a","b","c","d","e","f"]; var selectList:Array=allList.slice(1,4); //取り出した配列 trace(selectList);//出力:b,c,d //元の配列は変化しない trace(allList);//出力:a,b,c,d,e,fslice()は2番目の引数を省略できます。slice(3)のように引数を1つだけ指定した場合は3番目(並びでは4個目)から最後までの値を指定したことになります。
var allList:Array=["a","b","c","d","e","f"]; var selectList:Array=allList.slice(3); trace(selectList);//出力:d,e,f trace(allList);//出力:a,b,c,d,e,f引数をマイナスにすると末尾から個数を数えて取り出します。次の例は末尾から4個の値を取り出した配列を作ります。インデックス番号と違って1から数えるので注意してください。
var allList:Array=["a","b","c","d","e","f"]; var selectList:Array=allList.slice(-4); trace(selectList);//出力:c,d,e,f trace(allList);//出力:a,b,c,d,e,f
var colors:Array=new Array("red","yellow");
//値を先頭に挿入する
colors.unshift("black");
var cnt:uint=colors.unshift("white","gray");
trace(cnt);//出力:5
trace(colors);//出力:white,gray,black,red,yellow
逆にshift()は配列の先頭の値を抜き取るメソッドです。shift()で値を抜き取ると先頭の値が配列から削除されます。
var colors:Array = new Array("red", "yellow", "black");
var firstColor:String = colors.shift();
//取り出した値
trace(firstColor);//出力:red
//元の配列からは先頭の値が取り除かれている
trace(colors);//出力:yellow,black
//空の配列を作る
var colors:Array = new Array();
//値を追加する
colors.push("red");
colors.push("yellow","green");
//pushした順に値が追加されている
trace(colors);//出力:red,yellow,green
var cnt:uint=colors.push("black");
//pushすると配列の長さが返ってくる
trace(cnt);//出力:4
trace(colors);//出力:red,yellow,green,black
逆にpop()は配列の最後の値を抜き取るメソッドです。演算子[]で最後の値を取り出しても元の配列に入っている値はそのままですが、pop()で値を抜き取ると最後の値が配列から削除されます。 var colors:Array=["red","yellow","black"]; var lastColor:String=colors.pop(); //取り出した値 trace(lastColor);//出力:black //元の配列からは最後の値が取り除かれている trace(colors);//出力:red,yellow
ActionScript 3.0 言語およびコンポーネントリファレンスでLoaderクラスの説明を見ると継承には次のように書いてあります。
継承:Loader→DisplayObjectContainer→InteractiveObject →DisplayObject→EventDispatcher→Object
これを見ると確かにLoaderクラスはDisplayObjectContainerクラスを継承しているので、MovieClipやSpriteなどと同じようにaddChild()を使って入れ子の表示オブジェクトを追加できるはずです。しかし実際にはLoaderが表示できるのは読み取り専用のcontantプロパティで参照できる表示オブジェクトだけです。
その理由はコンポーネントリファレンスの説明の続きに書いてあります。そこには次のように書いてあります。
Loader クラスは、継承する次のメソッドをオーバーライドします。これは、Loader オブジェクトが持つことができるのは 1 つの子表示オブジェクト、つまり読み込むオブジェクトに限られているためです。次のメソッドを呼び出すと例外がスローされます。メソッドは、addChild()、addChildAt()、removeChild()、removeChildAt() および setChildIndex() です。読み込まれた表示オブジェクトを削除するには、親の DisplayObjectContainer 子配列から Loader オブジェクトを削除する必要があります。
p.225の表示リストの図でLoaderを二重枠にしていない理由はそういうわけでした。