前回の第30回「マウスイベントとインスタンスの兄弟・親子の関係」に引続き,今回もマウスイベントの扱いをお題にする。とくに,マウスのロールオーバーをネタに,複数のインスタンスを含んだマウスイベントの捉え方について解説したい。
InteractiveObject.mouseOverとInteractiveObject.rollOverイベント
マウスのロールオーバーを捉えるイベントには,InteractiveObject.mouseOver(定数MouseEvent.MOUSE_OVER)とInteractiveObject.rollOver(定数MouseEvent.ROLL_OVER)がある(※1)。このふたつのイベントの違いについて調べるムービーをつくってみよう。MovieClipシンボル(シンボル名Parent)の中に,ふたつの MovieClipインスタンスを入れ子にする。ふたつのインスタンス名は,それぞれpen0_mcとpen1_mcだ(図1)。
このMovieClipシンボルのインスタンスをひとつメインタイムラインに配置し,インスタンス名はparent_mcとする。イベントInteractiveObject.mouseOverとInteractiveObject.rollOverとは,そのターゲットのインスタンスをどう捉えるかが違っている。親のMovieClipインスタンスparent_mcの第1フレームアクションに以下のスクリプト1を書き,ふたつのイベントにリスナー関数xTraceを登録する(図2)。
スクリプト1 イベントInteractiveObject.mouseOverとInteractiveObject.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);
}
リスナー関数xTrace()は,受取ったイベントオブジェクトから,3つのプロパティを取出す。Event.typeとEvent.targetおよびEvent.currentTargetプロパティだ。ただし,後のふたつはインスタンスが区別できるようDisplayObject.nameプロパティを調べたうえで,trace()関数により3つの情報を[出力]する。なお,シンボル内に入れ子にしたふたつのインスタンスには,名前をつけたほかはとくに設定はしていない。
[ムービープレビュー]して,入れ子の一方のMovieClipインスタンス(pen0_mc)にマウスポインタを重ねると,イベントInteractiveObject.mouseOverとInteractiveObject.rollOverがともに発生する。ただし,つぎのようにEvent.targetプロパティのインスタンスの[出力]が異なる。
rollOver parent_mc parent_mc
mouseOver pen0_mc parent_mc
InteractiveObject.mouseOverイベントではマウスポインタを重ねた子のインスタンスが捉えられているのに対し,InteractiveObject.rollOverイベントはリスナーを登録した親に発生したものと扱われるのだ。
さらに,マウスポインタを他方のインスタンス(pen1_mc)の上に移すと,InteractiveObject.mouseOverイベントはインスタンスpen1_mcに対して改めて発生する。しかし,InteractiveObject.rollOverイベントは起こらない(図3)。つまり,InteractiveObject.mouseOverイベントは子インスタンスごとに,InteractiveObject.rollOverイベントはリスナーが登録されたインスタンスをひとつとみなして発生するのである。
- ※1
- マウスポインタのロールアウトを扱うイベントは,ロールオーバーのイベントInteractiveObject.mouseOverとInteractiveObject.rollOverに対応して,それぞれInteractiveObject.mouseOutとInteractiveObject.rollOutがある。
子のインスタンスに対するマウスイベントの発生を止める
マウスのロールオーバーについては,子インスタンスごとにイベントを受取りたいときはInteractiveObject.mouseOver,リスナーを登録した親インスタンスでまとめて捉えたいときにはInteractiveObject.rollOverと,ふたつを使い分ければよいと一応はいえる。しかし,InteractiveObject.mouseOverイベントを使いつつ,子インスタンスごとではなく,親インスタンスでまとめて扱いたい場合があるかもしれない。
それだけでなく,マウスクリックを捉えるInteractiveObject.clickイベントも,実は子インスタンスごとに発生する。つまり,前述のムービーのようにふたつの子インスタンスが入れ子になっている場合(前掲図3参照),一方の子インスタンス上でマウスボタンを押したまま,ポインタを他方のインスタンス上に移してボタンを放したとき,InteractiveObject.clickイベントは発生しない。しかも,ロールオーバーと違って,クリックを親インスタンスでまとめて受取るイベントというものは別に用意されてない。
そうなると,子インスタンスごとにイベントを発生させない手段が知りたい。ひとつは,前回紹介したInteractiveObject.mouseEnabledプロパティをfalseにすることだ。すると,子インスタンスへのマウスイベントは親インスタンスが直接受取れる。ただし,その設定をしていない子インスタンスは,相変わらず自分に対するマウスイベントと捉えてしまう。したがって,マウスイベントを親インスタンスがまとめて受取るためには,すべての子インスタンスのInteractiveObject.mouseEnabledプロパティをfalseにしなければならない(図4)。
pen0_mc.mouseEnabled = false;
pen1_mc.mouseEnabled = false;
もうひとつ,子インスタンスごとにマウスイベントが発生しないように,親インスタンスのプロパティを使って設定できる。DisplayObjectContainer.mouseChildrenプロパティをfalseにすると,その子インスタンスはマウスイベントを自分に対して受取らなくなり,親インスタンスへのイベントとして扱われる(図5)。すると,InteractiveObject.mouseOverイベントも,InteractiveObject.rollOverと同じ動きになる。
mouseChildren = false;

