【ActionScript 3.0 Mailing List開設!】
F-siteセミナー
イベントを制する者、ActionScript 3.0を制す
Date: 2007年11月10日 |
Product: Flash |
Platform: All |
Viersion: CS3/ActionScript 3.0 |
ボクシングでは「左を制する者は世界を制す」といわれるらしい。「左」つまり「ジャブ」の重要性を伝えることばだ。ActionScriptにおいては、「イベント」がその基礎を成す。ActionScript 3.0では、そのイベントの扱い方や考え方が、2.0/1.0とは大きく変わった。そのポイントについて、マウスイベントを題材にして紹介する。
1. マウスイベントを受取る
ActionScript 1.0でMovieClipアクションにスクリプトを記述するFlash 5スタイル(図001)では、on()イベントハンドラアクションでマウスイベントを受取る。マウスクリックを扱うイベントは、release(スクリプト001)[*1]。
図001■MovieClipインスタンスにon()ハンドラを記述する
スクリプト001■クリックを受取るMovieClipアクション ー ActionScript 1.0
// MovieClip: クリックを受取るインスタンス
// MovieClipアクション
on (release) {
trace(this);
}
|
ActionScript 3.0でFlashムービー内にスクリプトを記述するには、フレームアクションでリスナー関数を定義する(図002)。リスナー関数は、addEventListener()メソッドを使ってMovieClipインスタンスに登録する。マウスイベントのクリックは、click(MouseEvent.CLICK)を指定する(スクリプト002)[*1]。
図002■フレームアクションにリスナー関数を定義する
スクリプト002■クリックを受取るフレームアクション ー ActionScript 3.0
// MovieClip: クリックを受取るインスタンス
// 第1フレームアクション
addEventListener(MouseEvent.CLICK, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(this, this.name);
}
|
MovieClipインスタンスをボタンとしてふるまわせる(指差しカーソルへの変更など。図003)には、buttonModeプロパティをtrueに設定する必要がある(スクリプト003)。
図003■MovieClipインスタンス上で指差しカーソルに変わる
スクリプト003■buttonModeプロパティをtrueに設定する
// MovieClip: クリックを受取るインスタンス
// 第1フレームアクション
addEventListener(MouseEvent.CLICK, xTrace);
buttonMode = true;
function xTrace(eventObject:MouseEvent):void {
trace(this, this.name);
}
|
[*1] ActionScript 2.0/1.0では、trace()関数の引数にMovieClipインスタンスを渡すと、そのパスが[出力]された。しかし、ActionScript 3.0は、原則としてインスタンスのクラス名を[出力]する。したがって、インスタンス名を知りたい場合には、nameプロパティを調べる必要がある。
なお、ActionScript 3.0のtrace()関数は、複数の引数が指定できる。[出力]パネルには、それらの(文字列表現された)値が、スペース区切りで表示される。
|
2. ダブルクリックを受取る
ActionScript 3.0のマウスイベントには、ダブルクリックが加わった。イベントの指定はdoubleClick(MouseEvent.DOUBLE_CLICK)だ。ただし、イベントリスナーを登録しただけでは足りない[*2]。インスタンスのdoubleClickEnabledブロパティをtrueに設定する必要がある(スクリプト004)。
スクリプト004■ダブルクリックを受取るフレームアクション
// MovieClip: クリックを受取るインスタンス
// 第1フレームアクション
addEventListener(MouseEvent.CLICK, xTrace);
addEventListener(MouseEvent.DOUBLE_CLICK, xTrace);
buttonMode = true;
doubleClickEnabled = true;
function xTrace(eventObject:MouseEvent):void {
trace(this, this.name, eventObject.type);
}
|
リスナー関数が引数として受取ったイベントオブジェクトのtypeプロパティを調べると、イベント名が文字列で取得できる。たとえば、上記スクリプト004からは、つぎのような[出力]が得られる(MovieClipインスタンスのシンボル名"Pen")。
[object Pen_1] my_mc click
[object Pen_1] my_mc doubleClick
[*2] [ActionScript 3.0コンポーネントリファレンスガイド]の「InteractiveObject.doubleClickEnabled」の項には、「このプロパティを設定すると、イベントは送出されなくなります」と説明されている。しかし、これは邦訳の誤りだと思われる。英語の原文は、"No event is dispatched by setting this property"(このプロパティを設定しても、イベントは配信されない)とし、イベントリスナーの登録が別途必要である旨を述べているのである(「Flash CS3ヘルプ正誤表」参照)。
|
3. イベントは誰に対して発生するか
ActionScript 3.0では、ひとつひとつのインスタンスがイベントを受取る。イベントを処理するスクリプトが書かれているかどうかは問わない[*3]。
したがって、別のMovieClipインスタンスを前面に置くと、背後のインスタンスにはイベントが渡らなくなる(図004)。
図004■MovieClipインスタンスが前にあると指差しカーソルに変わらない
前面のMovieClipインスタンスにマウスイベントを受取らせないようにするには、そのインスタンスのmouseEnabledプロパティをfalseに設定する(スクリプト005)。
スクリプト005■MovieClipインスタンスにマウスイベントを受取らせない
// メインタイムライン
// 第1フレームアクション
// front_mcにマウスイベントを受取らせない
front_mc.mouseEnabled = false;
|
マウスポインタを動かしたときのmouseMove(MouseEvent.MOUSE_MOVE)イベントをステージ全体について受取りたいときは、イベントリスナーはstageプロパティ[*4]をターゲットにして登録する(スクリプト006)。
ActionScript 2.0/1.0のイベントには、発生したインスタンスに対するものと、インスタンスを問わないものがある(図005)。
スクリプト006■ステージ全体に対するmouseMoveイベントを受取る
// メインタイムライン
// MovieClipインスタンスmy_mcを配置
// 第1フレームアクション
// my_mc.addEventListener(MouseEvent.MOUSE_MOVE, xTrace);
// addEventListener(MouseEvent.MOUSE_MOVE, xTrace);
stage.addEventListener(MouseEvent.MOUSE_MOVE, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(eventObject.target, eventObject.target.name);
}
|
図005■onClipEvent(mouseMove)ハンドラはイベントの発生したインスタンスを問わない
イベントオブジェクトのtargetプロパティにより、イベントが発生したインスタンスを取得できる。イベントの発生したインスタンスとイベントを処理する(リスナー関数を登録した)インスタンスとは、必ずしも一致しない(図006)。
図006■イベントの発生するインスタンスはポインタ位置によって変わる
[*3] ActionScript 2.0/1.0では、イベントハンドラが設定されていないMovieClipインスタンスは、マウスイベントを受取らない。
[*4] ActionScript 3.0では、直接Stageクラスが参照できない。stageプロパティを経て、Stageクラスにアクセスする必要がある。
|
4. イベントの発生と処理
ActionScript 3.0のイベントは、発生したインスタンス自身に加え、表示階層(ディスプレイリスト)の親が受取って処理できる。とくにマウスイベントでは、誰に発生したイベントを、誰が処理するのか考えなければならない。
mouseOver(MouseEvent.MOUSE_OVER)とrollOver(MouseEvent.ROLL_OVER)のイベントでは、それが発生したインスタンスの捉え方が異なる。イベントを処理しているインスタンスは、イベントオブジェクトのcurrentTargetプロパティで調べることができる。
MovieClipインスタンスparent_mcに対するmouseOverとrollOverイベントの両方に、同じリスナー関数を登録して、イベントオブジェクトのtargetとcurrentTargetのインスタンス名を[出力]してみる(スクリプト007)。
なお、このフレームアクションを設定したMovieClipシンボル内には、ふたつのMovieClipインスタンスpen0_mcとpen1_mcを配置した(図007)。
スクリプト007■mouseOverとrollOverイベントの両方にリスナー関数を設定
// MovieClip: マウスイベントを処理するparent_mc
// MovieClipインスタンスpen0_mcとpen1_mcを配置
// 第1フレームアクション
addEventListener(MouseEvent.MOUSE_OVER, xTrace);
addEventListener(MouseEvent.ROLL_OVER, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(eventObject.type, eventObject.target.name, eventObject.currentTarget.name);
}
|
図007■MovieClipシンボル内にはふたつのMovieClipインスタンスを配置
[ムービープレビュー]を確認すると、parent_mcインスタンス内の子のMovieClipインスタンスpen0_mcとpen1_mcのどちらかにマウスポインタを重ねれば、mouseOverとrollOverのイベントがともに発生する。たとえば、インスタンスpen0_mcの領域内にポインタを入れると、つぎのように[出力]される。
rollOver parent_mc parent_mc
mouseOver pen0_mc parent_mc
ところが、一部が重なり合ったもう一方のインスタンス上にポインタを動かすと、インスタンスparent_mcの領域は出ていないのにも拘らず、mouseOverイベントが改めて起こる。たとえば、インスタンスpen0_mcからpen1_mc上にポインタを移動させると、つぎのような[出力]になる(図007)。
mouseOver pen1_mc parent_mc
rollOverイベントでは、イベントオブジェクトのtargetとcurrentTargetのプロパティが、ともにイベントリスナーを登録したインスタンスparent_mcになっている。つまり、MovieClipシンボル内のインスタンスごとに、イベントの発生を区別していないことがわかる。
MovieClipシンボル内のインスタンスについて、mouseEnabledプロパティをfalseに設定すれば、マウスイベントは独立して発生しなくなる(イベントリスナーを登録したインスタンスについて発生したイベントとみなされる)。
MovieClipシンボル内のすべてのインスタンスについて独立したマウスイベントを発生させないようにするには、mouseChildrenプロパティをfalseに設定する(スクリプト008)。そうすると、mouseOverとrollOverで、マウスイベントが同じように扱われる。
スクリプト008■イベントリスナー登録先インスタンスのmouseChildrenプロパティをfalseに設定する
// MovieClip: マウスイベントを処理するparent_mc
// MovieClipインスタンスpen0_mcとpen1_mcを配置
// 第1フレームアクション
addEventListener(MouseEvent.MOUSE_OVER, xTrace);
addEventListener(MouseEvent.ROLL_OVER, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(eventObject.type, eventObject.target.name, eventObject.currentTarget.name);
}
mouseChildren = false;
|
[ムービープレビュー]で確認すると、MovieClipシンボル内のいずれのインスタンスにポインタを重ねても、以下のように[出力]される(インスタンス間でポインタを移動しても、イベントは発生しない)。
rollOver parent_mc parent_mc
mouseOver parent_mc parent_mc
5. 親子によるイベントの連携処理
mouseUp(MouseEvent.MOUSE_UP)イベントは、clickとは異なり、マウスボタンを放す操作だけに注目する。したがって、インスタンスの外でマウスボタンを押した場合も、インスタンス上で放せばイベントが呼出される。
他方、clickイベントは、リスナーを登録したインスタンス内であっても、マウスボタンを押した子のインスタンスと放したインスタンスとが異なれば発生しない。
以下のスクリプト009はマウスクリックの操作について、同007と同じ要領で、mouseUpとclickイベントとの違いを確かめることができる。
スクリプト009■clickとmouseUpイベントの違いを確かめる
// MovieClip: マウスイベントを処理する
// MovieClipインスタンスpen0_mcとpen1_mcを配置
// 第1フレームアクション
addEventListener(MouseEvent.CLICK, xTrace);
addEventListener(MouseEvent.MOUSE_UP, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(eventObject.type, eventObject.target.name, eventObject.currentTarget.name);
}
|
mouseUpイベントは、インスタンス上でマウスボタンを押すmouseDown(MouseEvent.MOUSE_DOWN)と組合わせて使われる場合が多い。ひとつのインスタンスに対するイベントを子と親で連携して扱えるということは、ひとつのボールをめぐってダプルスで連携してプレイするのに似ている。
ここで、クリックしたインスタンスの外でマウスボタンを放す操作、ActionScript 2.0/1.0のreleaseOutsideイベントを、ActionScript 3.0で実装してみる[*5]。戦略は、こうだ。ダブルスの前衛をボタン用インスタンス、後衛をステージとする。
- 前衛のボタン用インスタンスがコートに入り、サーブのmouseDown(マウスボタンの押す操作)をレシーブする。
- 前衛の呼びかけに応じて後衛のステージがコートに入り[*6]、ふたりでつぎに返されるmouseUp(マウスボタンの放す操作)を待つ。
- mouseUpが前衛の守備領域であるボタンのインスタンス上でなされれば、前衛が返し、ボタンのインスタンス上のクリックとなる。前衛が受けなかったmouseUpは、ボタンのインスタンス外の操作であり、後衛がレシーブする。
- リセットして、つぎのサーブを待つ。
上記戦略にしたがったスクリプトは、つぎのとおりだ(スクリプト010)[*7]。イベントリスナーから関数を削除するには、removeEventListener()メソッドを用いる。引数は、addEventListener()メソッドと変わらない。
スクリプト010■インスタンス領域外まで含めたマウスクリック操作を処理する
// MovieClip: マウスイベントを処理する
// 第1フレームアクション
addEventListener(MouseEvent.MOUSE_DOWN, xPress);
function xPress(eventObject:MouseEvent):void { // サーブを返す
trace("press");
// ふたりでmouseUpを待つ
addEventListener(MouseEvent.MOUSE_UP, xRelease);
stage.addEventListener(MouseEvent.MOUSE_UP, xReleaseOutside);
}
function xRelease(eventObject:MouseEvent):void { // 前衛がレシーブ
trace("release");
// リセット
removeEventListener(MouseEvent.MOUSE_UP, xRelease);
stage.removeEventListener(MouseEvent.MOUSE_UP, xReleaseOutside);
}
function xReleaseOutside(eventObject:MouseEvent):void { // 後衛がレシーブ
trace("releaseOutside");
// リセット
removeEventListener(MouseEvent.MOUSE_UP, xRelease);
stage.removeEventListener(MouseEvent.MOUSE_UP, xReleaseOutside);
}
|
[*5] ActionScript 3.0には、インスタンス上でマウスボタンを押し、インスタンス外で放す、2.0/1.0のreleaseOutsideに相当するイベントがない。
[*6] かつての軟式テニスのダブルスでは、実際レシーバーでないペアはコート外というルールだったらしい。
[*7] スクリプトをもう少し整理し、さらにActionScript 2.0と同じく、onPressやonRelease、onReleaseOutsideイベントハンドラメソッドを定義したサンプルは「EventDispatcher.addEventListener()メソッド」[訳者注*3]に掲載している(Flash 9 ActionScript 3.0 Previewをもとに解説していることに注意)。興味のある人は参考にしてほしい。
|
コリン・ムックの「今から始めるActionScript 3.0 - WORLD WIDE TOUR」
Adobeにて来年2008年1月15日火曜日に、『Essential Actionscript 2.0』の著者Colin MoockによるActionScript 3.0の無償トレーニング「今から始めるActionScript 3.0 - WORLD WIDE TOUR」が催されます。丸1日を使った初心者向けの講座です。通訳が入るタイムロスもあるとはいえ、有益な情報が得られそうです。
【日 時】2008年1月15日火曜日10:00-19:00
【参加費用】無料
【場 所】大崎ゲートシティウェストタワーB1(大崎駅徒歩3分)
【募集人数】300名
【予定内容】>>アジェンダ
・オブジェクト指向プログラミングのすべての主要概念
・クラスおよびオブジェクトの理解
・ActionScript 3.0プログラムの構築および記述方法
・Flex Builder 2の開発環境
・ActionScript3.0主要概念のレビュー
|
作成者: 野中文雄
作成日: 2007年11月11日
ドラフト作成: 2007年11月10日