‘AS3’ カテゴリーのアーカイブ

FlashDevelop.org :: View topic - Special tags (parameters) in Snippets

2008 年 5 月 1 日 木曜日

FlashDevelop.org :: View topic - Special tags (parameters) in Snippets


FlashDevelopのテンプレートなどで使われている(と思う)特別なタグの仕様。

ActionScript 3.0 のイベント伝播を学ぶ

2008 年 4 月 14 日 月曜日

AS3 のイベント処理。AS2 時代の EventDispatcher 経験で、なあなあに作って来たのですが、諸般の事情で bubble とか useCapture を知る事に決めました。

何はともあれ Adobe の公式資料です。しっかり書いてあります。

まず Flash CS3 ドキュメンテーションですっきり紹介されていて、イベント伝播の往路と復路が関係してくる事が分かります。
  1. キャプチャ段階: Stage からイベントターゲットまでのオブジェクトに於けるイベント伝播
  2. ターゲット段階:イベントターゲットに於けるイベント伝播
  3. バブリング段階:イベントターゲットから Stage までのオブジェクトに於けるイベント伝播
イベントフローは三段階に見立てられる、と言う定義が分かりました。



そしてイベントを実際に扱うクラス・メソッドの解説も読みます。


EventDispatcher



addEventListener(type:String, listener:Function,

useCapture:Boolean = false):void




useCapture:Boolean (default = false) ― リスナーが、キャプチャ段階、またはターゲットおよびバブリング段階で動作するかどうかを判断します。useCapture を true に設定すると、リスナーはキャプチャ段階のみでイベントを処理し、ターゲット段階またはバブリング段階では処理しません。useCapture を false に設定すると、リスナーはターゲット段階またはバブリング段階のみでイベントを処理します。3 つの段階すべてでイベントを受け取るには、addEventListener を 2 回呼び出します。useCapture を true に設定して 1 度呼び出し、useCapture を false に設定してもう一度呼び出します。



Event



Event(type:String, bubbles:Boolean = false)



bubbles:Boolean (default = false) ― Event オブジェクトがイベントフローのバブリング段階で処理されるかどうかを判断します。デフォルト値は false です。


それぞれもっと引数が付くのですが、今回の話では割愛です。



addEventListener の useCapture についてまとめます。
  1. デフォルト( false )ではターゲット/バブリング段階のみ処理が行われる。
  2. true ならキャプチャ段階のみ処理が行われる。
  3. 故に、総ての段階を対象とするなら true / false で addEventListener を二回呼ぶ。


それでは次にEvent の bubbles 。

デフォルトの Event オブジェクトはバブリング段階で処理されない事が分かります。



ここは更に Event の定数らを見る事にします。すると、イベントによっては bubbles = true のイベントオブジェクトが在る事が分かります。

例えば Event.REMOVED は true です。

(ちなみに Event.REMOVED_FROM_STAGE は false )



ここまで得られた情報でイベント伝播の概要は掴めたので、何か書いてみます。



あるオブジェクトで Event.REMOVED_FROM_STAGE と Event.REMOVED が発生する毎に trace するコードです。

addEventListener の解説に在った様に true / false で二回呼んで総ての段階を対象とします。


package {

import flash.display.Sprite;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;

public class ExeEvent extends MovieClip{
var _grid:Sprite;

public function ExeEvent(){

_grid = new Sprite();
_grid.graphics.lineStyle( 4, 0x333333 );
_grid.graphics.drawRect( 0, 0, 200, 200 );
addChild( _grid );

var addTF:TextField = new TextField();
addTF.text = "ADD";
var removeTF:TextField = new TextField();
removeTF.text = "REMOVE";
removeTF.x = addTF.width;
addChild( addTF );
addChild( removeTF );

addTF.addEventListener( MouseEvent.CLICK, _addButton );
removeTF.addEventListener( MouseEvent.CLICK, _removeButton );

stage.addEventListener( Event.REMOVED, _onRemoved, true );
stage.addEventListener( Event.REMOVED, _onRemoved, false );
_grid.addEventListener( Event.REMOVED, _onRemoved, true );
_grid.addEventListener( Event.REMOVED, _onRemoved, false );

stage.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, true );
stage.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, false );
_grid.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, true );
_grid.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, false );

}

private function _onRemoved( event:Event ):void {
trace( “# _onRemoved ” + event.currentTarget.name);
trace( event.toString() );

}

private function _onRemovedFromStage( event:Event ):void {
trace( “$ _onRemovedFromStage ” + event.currentTarget.name);
trace( event.toString() );

}

private function _addButton( event:MouseEvent ):void {
var button:Sprite = new Sprite();
button.graphics.beginFill( 0xcccccc );
button.graphics.drawCircle( 10, 10, 10 );
button.graphics.endFill();
button.x = _grid.width * Math.random();
button.y = _grid.height * Math.random();
_grid.addChild( button );

button.addEventListener( Event.REMOVED, _onRemoved, true );
button.addEventListener( Event.REMOVED, _onRemoved, false );

button.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, true );
button.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, false );

}

private function _removeButton( event:MouseEvent ):void {
if ( _grid.numChildren > 0 ) {
_grid.removeChildAt( 0 );
}
}
}
}


次が出力例です。


# _onRemoved null
[Event type="removed" bubbles=true cancelable=false eventPhase=1]
# _onRemoved instance1
[Event type="removed" bubbles=true cancelable=false eventPhase=1]
# _onRemoved instance4
[Event type="removed" bubbles=true cancelable=false eventPhase=2]
# _onRemoved instance1
[Event type="removed" bubbles=true cancelable=false eventPhase=3]
# _onRemoved null
[Event type="removed" bubbles=true cancelable=false eventPhase=3]
$ _onRemovedFromStage null
[Event type="removedFromStage" bubbles=false cancelable=false eventPhase=1]
$ _onRemovedFromStage instance1
[Event type="removedFromStage" bubbles=false cancelable=false eventPhase=1]
$ _onRemovedFromStage instance4
[Event type="removedFromStage" bubbles=false cancelable=false eventPhase=2]


event.currentTarget.name を出力させましたが、Stage は name 属性が無いので null 出力です。

eventPhase の1・2・3がキャプチャ・ターゲット・バブリング段階に対応しています(eventPhase参照)。



  1. キャプチャ段階: Stage からイベントターゲットまでのオブジェクトに於けるイベント伝播
  2. ターゲット段階:イベントターゲットに於けるイベント伝播
  3. バブリング段階:イベントターゲットから Stage までのオブジェクトに於けるイベント伝播
以上、まさしく解説の通りにこの三段階を経てイベントが伝播する事を確認しました。