サイトトップ

Director Flash 書籍 業務内容 プロフィール

Adobe Flash非公式テクニカルノート

Event.stopPropagation()とEvent.stopImmediatePropagation()メソッドの違い

ID: FN1101001 Product: Flash CS3 and above Platform: All Version: 9 and above/ActionScript 3.0

Event.stopPropagation()Event.stopImmediatePropagation()メソッドは、ともにイベントの伝播を止めます。けれど、ふたつのメソッドの違いがわかりにくいようです(表001)。

表001■[ヘルプ]のEvent.stopPropagation()とEvent.stopImmediatePropagation()メソッドの説明
Eventクラスのメソッド 説明
stopPropagation() イベントフローの現在のノードに後続するノードで、イベントリスナーが処理されないようにします。このメソッドは、現在のノード(currentTarget)のイベントリスナーには影響しません。
stopImmediatePropagation() イベントフローの現在のノードおよび後続するノードで、イベントリスナーが処理されないようにします。このメソッドはすぐに有効になり、現在のノードのイベントリスナーに影響します。

01 Event.stopPropagation()とEvent.stopImmediatePropagation()メソッドの説明の違い
まずわかりにくいのは、[ヘルプ]の文章そのものでしょう。ただよく読むと、イベントが流れる(イベントフローの)「ノード」をふたつに分けて説明しています。イベントリスナーを登録している(Event.currentTargetプロパティ)現在の(現行)ノードと、後続するつぎのノードです。このふたつのノードの扱いを整理すると、次表002のとおりです。

表002■Event.stopPropagation()とEvent.stopImmediatePropagation()メソッドのノードの扱い
Eventクラスのメソッド イベントフローのノード
現行ノード つぎのノード
stopPropagation() 止めない(影響しない) 止める
stopImmediatePropagation() 止める(影響する) 止める

たとえば、マウスイベントは、デフォルトでは表示リストの階層における親インスタンスにも伝わります。これは具体的には、表示リストの親にもイベントオブジェクトが送られるということです。このイベントオブジェクトが伝わる流れを「イベントフロー」と呼びます。

現行ノードとは、Event.currentTargetプロパティの参照、つまりEventDispatcher.addEventListener()メソッドでリスナーを登録したインスタンスです。現行ノードのリスナーがマウスイベントを処理し終えると、デフォルトではイベントオブジェクトは親インスタンスに送られます(図001)[*1]

図001■イベントオブジェクトは現行ノードの処理が済んでからつぎのノードに送られる
図001

さて、改めて前掲表002を確かめましょう。Event.stopPropagation()メソッドは、親インスタンスなどのつぎのノードにはイベントオブジェクトを渡しません。けれど、現行ノードのリスナーには、イベントオブジェクトを送ります。それに対して、Event.stopImmediatePropagation()メソッドは、現行ノードにおけるイベントオブジェクトの流れも直ちに断ってしまうのです。

[*1] EventDispatcher.addEventListener()メソッドの第3引数にtrueを渡すと、イベントオブジェクトがキャプチャーフェーズで受取られます(「EventDispatcher.addEventListener()メソッド」参照)。この場合、つぎのノードは子インスタンスになります。


02 Event.stopPropagation()とEvent.stopImmediatePropagation()メソッドの違いを確かめる
それでは、テスト用のスクリプトでEvent.stopPropagation()Event.stopImmediatePropagation()メソッドの違いを確かめてみましょう。まず、メインタイムラインにMovieClipインスタンスをひとつ置き、インスタンス名はmy_mcとします(図002)。

図002■メインタイムラインにMovieClipインスタンスを置く
図002左図 図002右図

つぎに、以下のスクリプト001をメインタイムラインのフレームアクションとして書きます。MovieClipインスタンスと親のメインタイムラインおよびStageオブジェクトのInteractiveObject.clickイベント(定数MouseEvent.CLICK)に、それぞれふたつのリスナー関数(onClick0()とonClick1())を登録しています。ふたつのリスナー関数はともにtrace()関数で、関数の識別番号とEvent.currentTargetプロパティの値を[出力]します。

スクリプト001■連結リストのエレメントを生成するクラスElement
    // フレームアクション: メインタイムライン
  1. stage.addEventListener(MouseEvent.CLICK, onClick0);
  2. addEventListener(MouseEvent.CLICK, onClick0);
  3. my_mc.addEventListener(MouseEvent.CLICK, onClick0);
  4. stage.addEventListener(MouseEvent.CLICK, onClick1);
  5. addEventListener(MouseEvent.CLICK, onClick1);
  6. my_mc.addEventListener(MouseEvent.CLICK, onClick1);
  7. function onClick0(eventObject:MouseEvent):void {
  8.   // eventObject.stopPropagation(); // [1]
  9.   // eventObject.stopImmediatePropagation(); // [2]
  10.   trace(0, eventObject.currentTarget);
  11. }
  12. function onClick1(eventObject:MouseEvent):void {
  13.   trace(1, eventObject.currentTarget);
  14. }

先に登録したリスナー関数(onClick0())内に記述したEvent.stopPropagation()Event.stopImmediatePropagation()メソッドの呼出しは、まだコメントアウトしてあります(スクリプト001第8〜9行目)。したがって、[ムービープレビュー]してMovieClipインスタンスをクリックすると、MovieClipインスタンス、メインタイムライン、Stageオブジェクトの階層順に、ふたつのイベントリスナーが交互に処理されます。[出力]結果はつぎのとおりです。

0 [object MovieClip]
1 [object MovieClip]
0 [object MainTimeline]
1 [object MainTimeline]
0 [object Stage]
1 [object Stage]

MovieClipインスタンス

メインタイムライン

Stageオブジェクト

では、先に登録したリスナー関数(onClick0())内から呼出すEvent.stopPropagation()メソッド(スクリプト001第8行目[1])の行コメント区切り記号を外して有効にします。

    // リスナー関数
  1. function onClick0(eventObject:MouseEvent):void {
  2.   eventObject.stopPropagation(); // [1]
  3.   // eventObject.stopImmediatePropagation(); // [2]
  4.   trace(0, eventObject.currentTarget);
  5. }

Event.stopPropagation()メソッドの呼出しにより、親インスタンスにイベントが渡らなくなります。けれど、現行ノードのつぎのリスナー関数にはイベントオブジェクトが送られます。したがって、MovieClipインスタンスをクリックしたときの[出力]はつぎのように変わります。

0 [object MovieClip]
1 [object MovieClip]

先に登録したリスナー関数(onClick0())内のEvent.stopPropagation()メソッドの呼出しはコメントアウトに戻します(スクリプト001第8行目[1])。替わりに、Event.stopImmediatePropagation()メソッドの呼出しを有効にしましょう(第9行目[2])。

    // リスナー関数
  1. function onClick0(eventObject:MouseEvent):void {
  2.   // eventObject.stopPropagation(); // [1]
  3.   eventObject.stopImmediatePropagation(); // [2]
  4.   trace(0, eventObject.currentTarget);
  5. }

Event.stopImmediatePropagation()メソッドは、親インスタンスだけでなく、現行ノードのつぎのリスナーにもイベントオブジェクトを渡しません。つまり、MovieClipインスタンスをクリックしたとき呼出されるのは、インスタンスのマウスイベントに登録した初めのリスナー関数だけになります。

0 [object MovieClip]


作成者: 野中文雄
作成日: 2011年1月14日


Copyright © 2001-2011 Fumio Nonaka.  All rights reserved.