ActionScript 3.0では、イベントの扱いがきわめて重要です。本章では、マウスイベントを採上げて、その発生の仕組みや注意点をご説明します。
○04-01 ボタンとしての振舞い
ActionScript 3.0は、マウスイベントも他のイベントと同じく、イベントリスナーを使って処理します。マウスイベントは、ボタンで扱われることが多いでしょう。そこで、まずボタンとしての振舞いに少し焦点を当ててみます。
●Sprite.buttonModeプロパティ
ボタンのクリックは、InteractiveObject.clickイベント(定数MouseEvent.CLICK)にリスナー関数を登録すれば受取れます。たとえば、つぎの第1フレームアクションをボタンのMovieClipシンボルに記述すると、インスタンスをクリックしたときに、そのクラスまたはシンボル名(Tips 04-009「[出力]されるインスタンスの表記」参照)とインスタンス名が[出力]されます(図Tech04-001)。
// MovieClip: ボタンとして使用
// フレームアクション
addEventListener(MouseEvent.CLICK, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(this, name);
}
図Tech04-001■MovieClipインスタンスのMouseEvent.CLICKイベントにリスナー関数を登録

リスナー関数はインスタンスのクラスまたはシンボル名とインスタンス名を[出力]する。ポインタ形状は矢印のまま。
|
スクリプトは、正しく動作しました。しかし、ボタンの振舞いとしては、ひとつもの足りないことがあります。マウスポインタの形状が、指差しカーソルに変わらないことです。インスタンスをボタンとして動作させるためには、以下のようにSprite.buttonModeプロパティをtrueに設定します。なお、このプロパティのデフォルト値はfalseです。
// MovieClip: ボタンとして使用
// フレームアクション
buttonMode = true;
addEventListener(MouseEvent.CLICK, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(this, name);
}
[ムービープレビュー]を確かめると、インスタンスにマウスポインタを重ねたとき、指先カーソルに変化します(図Tech04-002)。このマウスポインタの形状の変化が、ボタンとしての振舞いのひとつです。
図Tech04-002■Sprite.buttonModeプロパティをtrueに設定すると指差しカーソルに変化する

Sprite.buttonModeプロパティは、インスタンスにボタンとして振舞わせるかどうかを設定する。
|
●ボタンのアニメーション
ボタンの振舞いの典型は、マウスポインタとのインタラクションでしょう。つまり、マウスポインタがインスタンスに重なった(ロールオーバーした)ときや、マウスボタンを押したときに、そのイメージを変えることです。このインタラクティブなアニメーションは、スクリプトはほとんど記述することなく、実現することが可能です。
ボタンとして使うMovieClipシンボル内に、マウスのインタラクションに対応した下表Tech04-001の3つの状態のイメージを作成し、それらを別々のフレームに配置します。そして、それぞれのフレームには、同表に記載された特別なフレームラベル名を設定するのです(図Tech04-003)。
表Tech04-001■正規表現で用いられる特殊な文字の一部
マウスとのインタラクション
|
フレームラベル名
|
ボタンのイメージ
(例) |
なし
|
_up
|
|
インスタンスにマウスポインタを重ねる
|
_over
|
|
インスタンス上でマウスボタンを押す
|
_down
|
|
[ムービープレビュー]を見ると、MovieClipインスタンスのフレームが連続して再生されてしまいます。つまり、"_up"、"_over"、"_down"のフレームがつぎつぎとアニメーション表示され、期待するボタンの振舞いになりません。しかし、ひとたびマウスポインタをインスタンスに重ねると、"_over"フレームが表示され、クリックすれば"_down"、マウスポインタをインスタンス外に出せば"_up"フレームのイメージになります。
つまり、マウスポインタを1度インスタンスに重ねさえすれば、それ以降は期待するボタンのアニメーションが実現するのです。だとすれば、最初に"_up"フレームで再生ヘッドを止めておけばよいことになります。第2フレームにラベル"_up"を設定した場合は、第1フレームアクションでMovieClip.nextFrame()メソッドを呼出せばよいでしょう(図Tech04-003)。このステートメントを加えたのが、以下のスクリプトTech04-001です。
図Tech04-003■_up/_over/_downのフレームラベルを各イメージに設定

ボタンとして振舞わせるには、Sprite.buttonModeプロパティをtrueに設定。そして、MovieClip.nextFrame()メソッドで、再生ヘッドを"_up"フレームに止める。
|
スクリプトTech04-001■ボタンとして動作させるフレームアクション
// MovieClip: ボタンとして使用
// フレームアクション
buttonMode = true;
addEventListener(MouseEvent.CLICK, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(this, name);
}
nextFrame();
|
Tips Tech04-001■フレームラベルを第2フレーム以降に設定する理由
図Tech04-003では、フレームアクションを第1フレームに記述し、フレームラベルは第2フレーム以降に設定しています。これは、フレームアクションが、無駄に繰返し処理されないためです。フレームラベル"_up"を第1フレームに設定すると、ボタンとして表示されるイメージが"_up"フレームに戻るたび、第1フレームアクションが繰返し実行されることになるからです。
|
Tips Tech04-002■ヒット領域の設定 ー Sprite.hitAreaプロパティ
ボタンとして反応する領域、いわゆるヒット領域を、ボタンのイメージと異なる形状に設定するには、その領域をMovieClip(またはSprite)インスタンスとして作成し、インスタンスのSprite.hitAreaプロパティに代入します。
ただし、ボタンとして使うMovieClipシンボル内にヒット領域のインスタンスを配置する場合には、後述するInteractiveObject.mouseEnabledプロパティをfalseにする必要があります。
|
なお、ボタンとして用いるMovieClipの作成について、詳しくは筆者サイトFumioNonaka.com「ActionScript 3.0に対応したMovieClipのボタンをつくる」(<http://www.fumiononaka.com/TechNotes/Flash/FN0706001.html>)をお読みください。
○04-02 ダブルクリックを受取る
ActionScript 3.0には、マウスイベントとしてダブルクリックが備わっています。イベントは、InteractiveObject.doubleClick(定数MouseEvent.DOUBLE_CLICK)です。ところが、このイベントに対して原則どおりリスナー関数を登録しても、ダブルクリックがイベントとして受取れません。
// MovieClip: ダブルクリックを受取るインスタンス
// フレームアクション
addEventListener(MouseEvent.DOUBLE_CLICK, xTrace); // イベントが受取れない
function xTrace(eventObject:MouseEvent):void {
trace(this, name, eventObject.type);
}
ダブルクリックのイベントを受取るには、インスタンスのInteractiveObject.doubleClickEnabledプロパティをtrueに設定しなければなりません(デフォルト値はfalse)。なお、併せてInteractiveObject.clickイベントにもリスナー関数を登録する(スクリプトTech04-002)と、ダブルクリックでマウスボタンを2回押す操作の1回目はクリック(InteractiveObject.clickイベント)として、2回目がダブルクリック(InteractiveObject.doubleClickイベント)としてイベントを受取ります。
スクリプトTech04-002■クリックとダブルクリックを受取る
// MovieClip: ダブルクリックを受取る
// フレームアクション
doubleClickEnabled = true;
addEventListener(MouseEvent.CLICK, xTrace);
addEventListener(MouseEvent.DOUBLE_CLICK, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(this, name, eventObject.type);
}
|
上記スクリプトTech04-002では、ふたつのイベントに対して同じリスナー関数(xTrace())を登録しました。しかし、リスナー関数本体におけるtrace()関数のステートメントは、インスタンス自身の参照(this)とその名前(DisplayObject.nameプロパティ)のほか、Event.typeプロパティの値を[出力]しています。したがって、イベント名の文字列によって、リスナー関数はどのイベントが発生して呼出されたのかを判別できます(図Tech04-004)。
図Tech04-004■クリックとダブルクリックのイベントに同じリスナー関数を登録

Event.typeプロパティの値で、発生したイベントがわかる。
|
Maniac! Tech04-001■[ヘルプ]の「InteractiveObject.doubleClickEnabled」の項の説明
[ヘルプ]の[ActionScript 3.0コンポーネントリファレンスガイド] > [InteractiveObject]の「InteractiveObject.doubleClickEnabled」の項には、「このプロパティを設定すると、イベントは送出されなくなります」と説明されています。しかし、これは邦訳の誤りだと思われます。英語の原文は、"No event is dispatched by setting this property"(このプロパティを設定しても、イベントは配信されません)と述べているだけです。つまり、イベントリスナーの登録が別途必要であることを示しているのです。
|
○04-03 イベントのターゲット
マウスイベントのターゲット、つまりマウスイベントを誰が受取るかについて考えてみましょう。マウスイベントを受取るインスタンスに、もうひとつ別のインスタンスを加えて、動作を詳しく確かめます。
●重なり合ったインスタンスに対するマウスイベントの発生
ActionScript 3.0では、イベントリスナーを登録したかどうかに拘らず、すべてのMovieClipインスタンスがマウスイベントのターゲットになります。そして、マウスイベントは、マウスポインタの位置にある最前面のインスタンスが排他的に受取ります。
たとえば、タイムラインに配置したMovieClipインスタンスmy_mcに、フレームアクションでInteractiveObject.clickイベントのリスナー関数を以下のように登録したとします。そして、その前面に別のMovieClipインスタンスを重ねると、そのインスタンスにはイベントリスナーを何も設定していなくても、背後のMovieClipインスタンスmy_mcにはマウスイベントが渡らなくなります(図Tech04-005の右図)。
my_mc.buttonMode = true;
my_mc.addEventListener(MouseEvent.CLICK, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(eventObject.target, eventObject.target.name);
}
前面のMovieClipインスタンスfront_mcがマウスイベントを受取らないようにするには、InteractiveObject.mouseEnabledプロパティをfalseに設定する必要があります(スクリプト2-4-003)。すると、背面のMovieClipインスタンスmy_mcに、マウスイベントが渡ります。そのため、マウスポインタも、指差しカーソルに変わります(図Tech04-005左図)。なお、イベントオブジェクトのEvent.targetプロパティは、イベントの発生したインスタンスを参照します。
図Tech04-005■InteractiveObject.mouseEnabledプロパティをfalseにするとマウスイベントを奪わない
前面のインスタンスのInteractiveObject.mouseEnabledプロパティをfalseにすれば、背面のMovieClipインスタンスにマウスイベントが渡されるので、ポインタも指差しカーソルに変わる(左図)。プロパティを設定しないと、背面のインスタンスにはイベントが渡らない(右図)。
|
スクリプトTech04-003■前面のインスタンスのInteractiveObject.mouseEnabledプロパティをfalseに設定
// タイムライン: メイン
// フレームアクション
// マウスイベントを受取るMovieClipインスタンスmy_mcを配置
my_mc.buttonMode = true;
my_mc.addEventListener(MouseEvent.CLICK, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(eventObject.target, eventObject.target.name);
}
front_mc.mouseEnabled = false; // 前面のインスタンス
|
Tips Tech04-003■マウスイベントを受取るクラス
マウスイベントは、InteractiveObjectクラスが受取ります。InteractiveObjectクラスを継承するのは、MovieClipのほか、SpriteやSimpleButton、TextFieldクラスなどです。したがって、これらのインスタンスが、マウスイベントのターゲットになります。
|
AS1&2 Note Tech04-001■イベントハンドラがなければマウスイベントは受取らない
ActionScript 2.0では、イベントハンドラを設定したインスタンスがイベントを受取ります。その前面に別のMovieClipインスタンスを配置したとしても、前面のインスタンスはイベントハンドラが設定されないかぎり、マウスイベントを受取りません。したがって、背面のイベントハンドラを設定したインスタンスに、マウスイベントが渡ります。
|
[*イラスト候補●Tech04-001] マウスイベントは、最前面のインスタンスが独占する。
|
●表示リストの階層におけるマウスイベントの発生
インスタンス同士が同じ階層にあるのでなく、親子関係の入れ子になっている場合、イベントはどのように扱われるのでしょうか。今度は、マウスポインタが動いたときに発生するイベントInteractiveObject.mouseMove(定数MouseEvent.MOUSE_MOVE)のイベントリスナーを使って試してみることにします。
ActiolnScript 3.0のマウスイベントは、前述のとおりイベントのターゲットが、マウスポインタの座標にある最前面のインスタンスになります。したがって、つぎのフレームアクションのように、MovieClipインスタンスのInteractiveObject.mouseMoveイベントにリスナー関数を登録すると、マウスポインタがターゲットのインスタンス上を動いたときにしかイベントは発生しません。
addEventListener(MouseEvent.MOUSE_MOVE, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(eventObject.target, eventObject.target.name);
}
けれども、ActionScript 3.0のマウスイベントは、そのインスタンスの属する表示リストの親やさらに上層は、子に発生したイベントが扱える仕組みになっています。そして、表示リストの頂点に存在するStageインスタンスは、ステージ上のすべてのマウスイベントが受取れます。そこで、イベントリスナーをMovieClipインスタンスでなく、Stageオブジェクトに登録してみることにします(スクリプトTech04-004)。
スクリプトTech04-004■ステージ上のマウスポインタの移動を受取る
// MovieClip: 任意のインスタンス
// フレームアクション
stage.addEventListener(MouseEvent.MOUSE_MOVE, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(eventObject.target, eventObject.target.name);
}
|
[ムービープレビュー]で確かめると、ステージ全体でマウスポインタの動きに対してイベントが発生します。ただし、イベントの発生しているターゲットを示すイベントオブジェクトのEvent.targetプロパティは、MovieClipインスタンスの領域とその外では値が変化します。インスタンス上ではそのインスタンスの参照を、何もオブジェクトのない領域ではStageインスタンスを返します(図Tech04-006)
図Tech04-006■StageにMovieClip.onMouseMoveイベントハンドラメソッドを設定

イベントの発生したインスタンスであるEvent.targetプロパティの値は、マウスポインタがMovieClipインスタンス上かその外かによって変化する。
|
AS1&2 Note Tech04-002■MovieClip.onMouseMoveイベントハンドラメソッド
ActionScript 2.0/1.0のMovieClip.onMouseMoveイベントハンドラメソッドやonClipEvent(mouseMove)イベントハンドラアクションは、イベントが発生したインスタンスを問いません。したがって、マウスポインタがイベントハンドラを設定したMovieClipインスタンス上になくても、イベントは発生します。また、複数のインスタンスに同じイベントハンドラを設定すれば、それらのインスタンスはイベントを同時に受取ります。
|
○04-04 イベントの発生と処理
ActionScript 3.0では、イベントの発生するターゲットのインスタンスとは別に、イベントリスナーが登録されてイベントを処理するインスタンスが存在します。マウスイベントでは、イベントの発生したターゲットインスタンス自身のほか、そのインスタンスを表示リストのツリーに含む上層、つまり親や祖先のDisplayObjectContainerインスタンスがイベントを扱えます。そこで、イベントの発生するインスタンスとその処理を行うインスタンスについて、ロールオーバーとロールアウトのマウスイベントを採上げて説明しましょう。
Tips Tech04-004■イベントの発生するインスタンスと処理するインスタンス
デフォルトでは、イベントはまずターゲットのインスタンスに発生して、それから順に親(上層)に伝えられます。イベントの流れについて詳しくは、[ヘルプ] > [ActionScript 3.0のプログラミング] > [イベントの処理] > [イベントフロー]をお読みください。
なお、イベントによってはターゲットに対して発生するだけで、親に渡されないものもあります。たとえば、DisplayObject.enterFrameイベントがその例です。
[*筆者用参考] akihiro kamijo「イベントフロー」。
|
●InteractiveObject.mouseOverとInteractiveObject.rollOverイベント
マウスポインタのロールオーバーを扱うイベントには、InteractiveObject.mouseOver(定数MouseEvent.MOUSE_OVER)とInteractiveObject.rollOver(定数MouseEvent.ROLL_OVER)が定義されています。このふたつのイベントの違いは、イベントが発生するターゲットインスタンスの捉え方にあります。サンプルムービーとして、ステージに空のMovieClipインスタンスparent_mcを置き、その中にふたつのMovieClipインスタンスpen0_mcとpen1_mcを入れ子にします(図Tech04-007)。そして、ふたつの子のインスタンスにはスクリプトは書かず、親のparent_mcにつぎのフレームアクションを記述します(スクリプト2-4-005)。
図Tech04-007■MovieClipシンボル内にふたつのMovieClipインスタンスを入れ子にする

空のMovieClipインスタンスparent_mc内に、ふたつのMovieClipインスタンスpen0_mcとpen1_mcを配置。
|
スクリプトTech04-005■InteractiveObject.mouseOverとInteractiveObject.rollOverイベントにリスナー関数を登録
// MovieClip: マウスイベントを処理するparent_mc
// MovieClipインスタンスpen0_mcとpen1_mcを配置
// フレームアクション
addEventListener(MouseEvent.MOUSE_OVER, xTrace);
addEventListener(MouseEvent.ROLL_OVER, xTrace);
function xTrace(eventObject:MouseEvent):void {
trace(eventObject.type,
eventObject.target.name,
eventObject.currentTarget.name);
}
|
Tips Tech04-005■ロールアウトを扱うイベント
マウスポインタのロールアウトを扱うイベントは、ロールオーバーのイベントInteractiveObject.mouseOverとInteractiveObject.rollOverに対応して、それぞれInteractiveObject.mouseOutとInteractiveObject.rollOutになります。
|
スクリプトTech04-005は、親インスタンスparent_mcのふたつのイベントInteractiveObject.mouseOverとInteractiveObject.rollOverに、同じリスナー関数xTrace()を登録しています。関数xTrace()ではイベントオブジェクトから、イベント名を示すEvent.typeプロパティの文字列とイベントの発生したインスタンスであるEvent.targetの名前(DisplayObject.nameプロパティ)に加えて、Event.currentTargetが参照するインスタンスの名前をtrace()関数で[出力]しています。
このEvent.currentTargetプロパティが、リスナー関数の登録を受けて、イベントを処理しているインスタンスになります。ですから、スクリプトTech04-005を[ムービープレビュー]で試し、子のインスタンスの一方、たとえばpen0_mcにマウスポインタをロールオーバーすると、つぎのように[出力]されます。
rollOver parent_mc parent_mc
mouseOver pen0_mc parent_mc
リスナー関数は親のインスタンスparent_mcに登録しました。したがって、どちらの[出力]もEvent.currentTargetプロパティはparent_mcを参照しています。ところが、Event.targetプロパティが、InteractiveObject.rollOverイベントではやはりparent_mcであるのに対して、InteractiveObject.mouseOverイベントは実際にマウスポインタを重ねたpen0_mcになっています(図Tech04-008)。
図Tech04-008■InteractiveObject.mouseOverとInteractiveObject.rollOverのイベント発生の違い

InteractiveObject.mouseOverイベントは、内包する子のインスタンスごとにイベントの発生を区別。InteractiveObject.rollOverでは、リスナーを登録した親インスタンスでまとめてイベントを捉えている。
|
サンプルでは、ふたつの子のインスタンスは一部を重ね合わせてあります。そこで、マウスポインタをその重なった場所から、もう一方の子のインスタンスpen1_mc上に移動してみます。すると、InteractiveObject.mouseOverイベントは発生するものの、InteractiveObject.rollOverはイベントが起こりません(図2-4-008)。つまり、InteractiveObject.mouseOverイベントでは、内包する子のインスタンスひとつひとつについてイベントの発生を区別しています。それに対して、InteractiveObject.rollOverでは、中身の子はすべてひとまとめにして、リスナーを登録した親インスタンスでイベントを捉えているということがわかります。
●子のインスタンスに対するマウスイベントの発生を止める
マウスイベントを、内包する子のインスタンスごとに捉えるInteractiveObject.mouseOverなどで、子のインスタンスに対するマウスイベントを止め、親インスタンスでまとめて受取りたい場合があります。
ひとつの方法は、子のインスタンスについて、前述のInteractiveObject.mouseEnabledプロパティをfalseに設定することです。すると、その子のインスタンスに対するマウスイベントは、親インスタンスがターゲットとして認識されるようになります。ただし、その設定をしていない子インスタンスは、引続き自身をターゲットとしてマウスイベントを受取ります。
もうひとつの方法があります。子インスタンスについて個別にマウスイベントを発生させず、まとめて親インスタンスのイベントとして受取りたいときは、その親インスタンスのDisplayObjectContainer.mouseChildrenプロパティをfalseにします(表Tech04-002)。
表Tech04-002■マウスとのインタラクションを設定するプロパティ
クラス
|
プロパティ:データ型
|
説明
|
デフォルト値
|
InteractiveObject
|
mouseEnabled:Boolean
|
InteractiveObject(またはそのサブクラスの)インスタンスとマウスとのインタラクションを有効にするかどうかを、ブール(論理)値で指定します。falseに設定すると、インタラクションは無効になり、マウスイベントを受取らなくなります。
|
true
|
DisplayObjectContainer
|
mouseChildren:Boolean
|
表示リストに格納された子のInteractiveObject(またはそのサブクラスの)インスタンスとマウスとのインタラクションを有効にするかどうかを、ブール(論理)値で指定します。falseに設定すると、インタラクションは無効になり、マウスイベントを受取らなくなります。
|
true
|
たとえば、前記スクリプトTech04-005に以下のステートメントを加えると、子インスタンスpen0_mcとpen1_mcに対するマウスイベントがparent_mcに対して発生し、InteractiveObject.mouseOverとInteractiveObject.rollOverイベントの動作が同じになります。
mouseChildren = false;
つまり、イベントのターゲットインスタンス(Event.targetの値)はともにparent_mcとなり、一部が重なり合う子インスタンスpen0_mcとpen1_mcとの間でマウスポインタを移動しても新たなイベントは発生しません(図Tech04-009)。
図Tech04-009■DisplayObjectContainer.mouseChildrenプロパティをfalseに設定

子インスタンスに個別にマウスイベントが発生せず、まとめて親インスタンスがイベントを受取る。
|
[*筆者用参考] akihiro kamijo「Spriteとマウスイベント」。
○04-05 親子によるイベントの連携処理
マウスイベントの発生したターゲットインスタンスだけでなく、親インスタンスがその処理を行えることでどのような利点があるでしょう。それは、親と子が連携して、イベントを扱えることです。マウスイベントをもうふたつご紹介したうえで、親子で連携してイベントを処理する具体的な例についてご紹介します。
●インスタンスをクリックする操作
クリックをイベントとして受取るには、InteractiveObject.clickイベント(定数MouseEvent.CLICK)を用いるのが通常です。クリックというのは、インスタンス上でマウスボタンを押し、さらにその上で放す操作を意味します。InteractiveObject.clickイベントは、インスタンスに対してこのクリックの操作をすると発生します。
そして、InteractiveObject.clickイベントのターゲットは、子インスタンスを区別します(図Tech04-010)。したがって、イベントリスナーを登録した親DisplayObjectContainerインスタンスに複数のDisplayObjectインスタンスが含まれる場合、そのひとつの子インスタンス上でマウスボタンを押し、別の子インスタンス上でボタンを放したときには、イベントが発生しません。
図Tech04-010■InteractiveObject.clickイベントのリスナーを登録した親インスタンスの子は区別される

InteractiveObject.clickイベントのリスナーを登録した親インスタンスに子インスタンスが複数含まれると、マウスボタンを押した同じ子インスタンス上で放さないと、イベントが発生しない。
|
InteractiveObject.clickイベントを子インスタンスで区別せず、親インスタンスにまとめて扱いたいときは、もちろん親インスタンスのDisplayObjectContainer.mouseChildrenプロパティをfalseにすれば済みます。
ところで、インスタンス上でマウスボタンを押したものの、インスタンス外でボタンを放すという操作に対して処理が必要なこともあり得ます。ボタンであれば、押したまま気が変わって、やはりキャンセルしたという場合に当たります。このような処理を扱うときは、マウスボタンを押す操作と放す操作は分けた方が構成しやすいといえます。
ユーザーがインスタンス上でマウスボタンを押す操作はInteractiveObject.mouseDown(定数MouseEvent.MOUSE_DOWN)、放す操作はInteractiveObject.mouseUp(定数MouseEvent.MOUSE_UP)のイベントでそれぞれ受取ることができます(表Tech04-003)。それではつぎに、これらのイベントを使って、マウスボタンをインスタンス上で放した場合と、外で放した場合とをどのように切り分ればよいか考えてみましょう。
表Tech04-003■おもなマウスイベント
InteractiveObjectイベント |
イベントの説明 |
MouseEvent定数 |
click
|
ユーザーがポインティングデバイスの主ボタンを、同じInteractiveObjectインスタンスの上で押して放したときに配信されます。
|
CLICK : String = "click"
|
doubleClick |
ユーザーがポインティングデバイスの主ボタンを、同じInteractiveObjectインスタンスの上で素早く続けて2回押して放したときに配信されます。そのオブジェクトのdoubleClickEnabledプロパティは、trueに設定されている必要があります。
|
DOUBLE_CLICK : String = "doubleClick" |
mouseDown
|
ユーザーがポインティングデバイスの主ボタンを、InteractiveObjectインスタンスの上で押したときに配信されます。
|
MOUSE_DOWN : String = "mouseDown" |
mouseMove |
ユーザーがポインティングデバイスを、InteractiveObjectインスタンスの上で動かしているときに配信されます。 |
MOUSE_MOVE : String = "mouseMove" |
mouseOut |
ユーザーがポインティングデバイスを、InteractiveObjectインスタンスの上から外に動かしたときに配信されます。 |
MOUSE_OUT : String = "mouseOut" |
mouseOver |
ユーザーがポインティングデバイスを、InteractiveObjectインスタンスの上に動かしたときに配信されます。
|
MOUSE_OVER : String = "mouseOver" |
mouseUp |
ユーザーがポインティングデバイスの主ボタンを、InteractiveObjectインスタンスの上で放したときに配信されます。
|
MOUSE_UP : String = "mouseUp" |
mouseWheel |
ユーザーがポインティングデバイスのマウスホイールを、InteractiveObjectインスタンスの上で回したときに配信されます。このイベントは、Windows環境でのみ利用できます。
|
MOUSE_WHEEL : String = "mouseWheel" |
rollOut |
ユーザーがポインティングデバイスを、InteractiveObjectインスタンスの上から外に動かしたときに配信されます。
|
ROLL_OUT : String = "rollOut" |
rollOver |
ユーザーがポインティングデバイスを、InteractiveObjectインスタンスの上に動かしたときに配信されます。
|
ROLL_OVER : String = "rollOver" |
AS1&2 Note Tech04-003■MovieClip.onReleaseOutsideイベントハンドラメソッド
マウスボタンをインスタンス上で押したあとインスタンス外で放す操作は、ActionScript 2.0/1.0ではMovieClip.onReleaseOutsideイベントハンドラメソッドまたはon(releaseOutside)イベントハンドラアクションで扱うことができました。
|
●マウスボタンをインスタンス上で放したかどうかの切り分け
マウスボタンを放す操作は、InteractiveObject.mouseUpイベントで受取れました。イベントリスナーをインスタンスに登録すれば、そのインスタンス上でマウスボタンを放したことがわかります。インスタンス外でマウスボタンを放す操作は、Stageオブジェクトにイベントリスナーを加えることにより受取ることが可能です。
そこで、簡単な実験として、MovieClipシンボルの第1フレームアクションとして、以下のスクリプトを記述してみます。MovieClipインスタンスとStageオブジェクトのInteractiveObject.mouseUpイベントに、それぞれ別のリスナー関数を登録しています。
addEventListener(MouseEvent.MOUSE_UP, xRelease);
stage.addEventListener(MouseEvent.MOUSE_UP, xReleaseOutside);
function xRelease(eventObject:MouseEvent):void {
trace("release");
}
function xReleaseOutside(eventObject:MouseEvent):void {
trace("releaseOutside");
}
押したマウスボタンをMovieClipインスタンス外で放すと、Stageインスタンスに登録したリスナー関数が呼出されます。そして、インスタンス上でマウスボタンを放したときは、MovieClipインスタンスとStageオブジェクトのリスナー関数が順に呼ばれます(図Tech04-011)。MovieClipインスタンスをターゲットとしたInteractiveObject.mouseUpイベントは、表示リストの上位にあるStageインスタンスにも渡されるからです。
図Tech04-011■インスタンスとStageのInteractiveObject.mouseUpイベントにリスナー関数を登録

マウスボタンをMovieClipインスタンス上で放すと、インスタンスとStageオブジェクトのリスナー関数が順に呼出される。
|
さらに、MovieClipインスタンスのInteractiveObject.mouseUpイベントに登録したリスナー関数本体に、ステートメントを1行だけ追加します。Stageオブジェクトに登録したイベントリスナーを削除するEventDispatcher.removeEventListener()メソッドの呼出しです。
addEventListener(MouseEvent.MOUSE_UP, xRelease);
stage.addEventListener(MouseEvent.MOUSE_UP, xReleaseOutside);
function xRelease(eventObject:MouseEvent):void {
trace("release");
stage.removeEventListener(MouseEvent.MOUSE_UP, xReleaseOutside);
}
function xReleaseOutside(eventObject:MouseEvent):void {
trace("releaseOutside");
}
押したマウスボタンをMovieClipインスタンス外で放したときの動作は変わりません。しかし、インスタンス上でマウスボタンを放した場合、初めに呼出されるMovieClipインスタンスのリスナー関数内でStageオブジェクトのリスナー関数が削除されます。そのため、Stageインスタンスのリスナー関数は、もはや呼ばれません(図Tech04-012)。つまり、マウスボタンを放したのがMovieClipインスタンス上であればインスタンスのリスナー関数のみ、インスタンス外のときはStageオブジェクトのリスナー関数だけが呼ばれるようになったのです。
図Tech04-012■MovieClipインスタンスのリスナー関数でStageオブジェクトのイベントリスナーを削除

MovieClipインスタンス上でマウスボタンを放すと、リスナー関数内でStageオブジェクトのイベントリスナーが削除されるため、そのリスナー関数は呼出されなくなる。
|
もっとも、ひとたび削除されたStageインスタンスのリスナー関数は、改めて設定されることがありません。したがって、MovieClipインスタンス外でマウスボタンを放したとき、何も実行されなくなります。それだけでなく、もともとInteractiveObject.mouseUpイベントしか使っていませんので、マウスボタンはMovieClipインスタンス上にかぎらずどこで押してもイベントの処理が行われてしまいます。
イベントの流れを整理して、その扱いを正しく組立て直したのが、以下のスクリプトTech04-006です。第1に、MovieClipインスタンスに対するInteractiveObject.mouseDownイベントを受取ってから、インスタンス自身とStageオブジェクトのInteractiveObject.mouseUpイベントにリスナー関数を登録しています。これで、MovieClipインスタンス上でマウスボタンを押さなければ、マウスボタンを放す操作の処理も行われません。
第2に、MovieClipインスタンス上でマウスボタンを押してから放した場合には、それがインスタンス上であってもそうでなくても、MovieClipインスタンスとStageオブジェクトのInteractiveObject.mouseUpイベントに対するリスナー関数は削除しています。これは、第1の処理手順に対応した後処理になります。つまり、MovieClipインスタンス上でマウスボタンが押されて初めて放す操作のイベントリスナーを加えるということは、マウスボタンを放したらまたリスナー関数はクリアしなければならないからです。
スクリプトTech04-006■マウスボタンを放す操作がインスタンス上か外かで切り分ける
// MovieClip: マウスイベントを処理する
// 第1フレームアクション
addEventListener(MouseEvent.MOUSE_DOWN, xPress);
function xPress(eventObject:MouseEvent):void { // サーブを返す
trace("press");
// ふたりでmouseUpを待つ
xSetMouseUp();
}
function xRelease(eventObject:MouseEvent):void { // 前衛がレシーブ
trace("release");
// リセット
xClearMouseUp();
}
function xReleaseOutside(eventObject:MouseEvent):void { // 後衛がレシーブ
trace("releaseOutside");
// リセット
xClearMouseUp();
}
function xSetMouseUp():void {
addEventListener(MouseEvent.MOUSE_UP, xRelease);
stage.addEventListener(MouseEvent.MOUSE_UP, xReleaseOutside);
}
function xClearMouseUp():void {
removeEventListener(MouseEvent.MOUSE_UP, xRelease);
stage.removeEventListener(MouseEvent.MOUSE_UP, xReleaseOutside);
}
|
この処理の流れは、テニスのダブルスにも似ています。前衛はMovieClipインスタンスで、後衛がStageオブジェクトです。それぞれがイベントリスナーの登録を受けて、マウス操作に対応します。
- 前衛のMovieClipインスタンスがコートに入り、ユーザーの繰出すサーブのInteractiveObject.mouseDownイベントがインスタンスの守備範囲、つまりインスタンス上に入ったらそれをレシーブします。
- 前衛がレシーブしたのを確認したら後衛のStageもコートに加わり、ふたりでつぎに返されるInteractiveObject.mouseUpイベントを待受けます。
- InteractiveObject.mouseUpイベントが前衛の守備領域であるインスタンス上で起これば、クリックとして前衛のインスタンスが返します。前衛が受けなかったInteractiveObject.mouseUpイベントは、ボタンのインスタンス外の操作として後衛のStageがレシーブします。
- 1回分の攻防は終わったので、リセットしてまた前衛がつぎのサーブを待ちます。
ポイントは上記の3です。MovieClipインスタンスとStageオブジェクトは、親子ダブルスでInteractiveObject.mouseUpイベントを待受けています。マウスボタンを放す操作がインスタンス上で行われたかどうか切り分けようとした場合、通常は条件判定の処理が想い起こされるはずです。しかし、ここではMovieClipインスタンスとStageオブジェクトは、それぞれ自らの担当範囲を守り、自分の仕事をしているだけです。親子のダブルスで臨んだことにより、条件判断をすることなしに、守備の分担としてイベントが扱えたことにご注目ください。
[*イラスト候補●Tech04-002] 前衛のインスタンスと後衛のStageで、マウスイベントを待受ける。
|
[Prev/Next]
作成者: 野中文雄
作成日: 2008年7月20日