サイトトップ

Director Flash 書籍 業務内容 プロフィール
  ActionScript 3.0 Mailing List開設! 現在公開中の講座一覧

Adobe + ROKUNANA presents Flash 8 INSPIRATION SCENE Summer Jam

Flash 9 ActionScript 3.0 Previewのイベントリスナーとクラス定義

Date: 2006年9月6日 Product: Flash

Platform: All
Viersion: 9.0

サンプルソースファイル (zip圧縮/Flash 8およびFlash 9形式/約48KB)

□01 ActionScript 1.0/2.0から3.0にスクリプトを書替える
●Flash 5スタイルのMovieClipアクション
ActionScript 3.0は、2.0と同じECMAScript 4準拠[*1]。しかし、クラスの構成やイベントの扱い、細かなプロパティ・メソッドの仕様が変わった。ヘルプなどのドキュメントを、よく確認する必要がある。

つぎのFlash 5スタイルのMovieClipアクション(スクリプト001)を設定したMovieClipインスタンスは、水平方向にバネ運動のようなアニメーション(単振動)を行う(図001)[*2][*3]

図001■MovieClipインスタンスにMovieClipアクションを設定
MovieClipアクション

スクリプト001■インスタンスを水平に揺らすMovieClipアクション(event_handler_action.fla)

// MovieClip: アニメーションするインスタンス
// MovieClipアクション
onClipEvent (load) {
  var nCenterX:Number = Stage.width/2;
  var nCenterY:Number = Stage.height/2;
  var nRadian:Number = 0;
  var nRadiusX:Number = 100;
  var nRadiusY:Number = 60;
  _x = nCenterX;
  _y = nCenterY;
}
onClipEvent (enterFrame) {
  nRadian += 0.1;
  _x = nCenterX+nRadiusX*Math.cos(nRadian);
}

onClipEvent (load)ハンドラは初期設定(垂直方向の値は当面使わず、後に作成するスクリプトで利用)。onClipEvent (enterFrame)ハンドラは、ラジアン角を表す変数に0.1ずつ加算し、インスタンスに水平方向の単振動のアニメーションを行わせている。

[*1] Flash Player 9およびActionScript 3.0の概要については、「AdobeのFlash担当者に訊く - Flash Player 9とActionScript 3.0何が変わる?」(06/06/20)を参照。

[*2] スクリプトはActionScript 1.0のFlash 5スタイルを採っているものの、ActionScript 2.0の「厳密な型指定」を用いている。

「厳密な型指定」について詳しくは、Flash 8オンラインヘルプの「データ型の割り当てと厳密な型指定について」参照。

[*3] 直線上におけるバネのような振動(単振動)は、振動の中心をa、振幅をbとし、振動のスピードを決め、直線的に変化する変数をθとすると、振動する位置xはつぎの式で表せる。

x = a + b×cos(θ)

なお、単振動などの運動については、Wikipedia「振動運動」が詳しい。

●Flash MXスタイルのフレームアクション
スクリプト001を、Flash MXスタイルの第1フレームアクションに移行(スクリプト002)。onClipEvent (load)ハンドラは削除して、ハンドラ内に記述されていたステートメントを直接フレームに記述。

onClipEvent (enterFrame)イベントハンドラアクションは、MovieClip.onEnterFrameイベントハンドラメソッドに書替える。イベントハンドラメソッドは、関数(function)として定義[*4]

スクリプト002■インスタンスを水平に揺らすフレームアクション(event_handler_method.fla)

// MovieClip: アニメーションするインスタンス
// 第1フレームアクション
var nCenterX:Number = Stage.width/2;
var nCenterY:Number = Stage.height/2;
var nRadian:Number = 0;
var nRadiusX:Number = 100;
var nRadiusY:Number = 60;
_x = nCenterX;
_y = nCenterY;
function onEnterFrame():Void {
  nRadian += 0.1;
  _x = nCenterX+nRadiusX*Math.cos(nRadian);
}


[*4] スクリプト002のイベントハンドラメソッドMovieClip.onEnterFrameイベントハンドラメソッドは、つぎのように名前のない関数で定義することもできる。

this.onEnterFrame = function():Void {
  // ステートメント
};

なお、名前のない関数については、「名前のない関数(匿名関数/関数リテラル)」を参照。

●ActionScript 3.0のフレームアクション
スクリプト002を、ActionScript 3.0で動くように書替える(スクリプト003)。

(1)クラスやプロパティの仕様が、一部変更。Stageクラスは、MovieClipインスタンスのDisplayObject.stageプロパティを通して参照する。また、ActionScript 3.0のプロパティには、先頭にアンダースコア(_)がつかない。

(2)ActionScript 3.0では、EventDispatcher.addEventListener()メソッドを用いて、イベントを指定し、呼出す関数(リスナー関数)をイベントリスナーとして登録する。EventDispatcher.addEventListener()メソッドのシンタックス(構文)は、つぎのとおり[*5]

[ターゲットインスタンス].addEventListener(イベント, リスナー関数)

スクリプト003は、引数のイベントとして文字列"enterFrame"を指定。リスナー関数はイベントと同名にした(リスナー関数名は任意)。インスタンスに対して指定のイベントが発生すると、リスナー関数が呼出され、イベントオブジェクトと呼ばれる各種の情報を収めたオブジェクトが渡される[*6]。なお、関数に戻り値がない場合のデータ型は、void

スクリプト003■ActionScript 3.0のフレームアクション(as3_event_listener1.fla)

// MovieClip: アニメーションするインスタンス
// 第1フレームアクション
var nCenterX:Number = stage.stageWidth/2;
var nCenterY:Number = stage.stageHeight/2;
var nRadian:Number = 0;
var nRadiusX:Number = 100;
var nRadiusY:Number = 60;
x = nCenterX;
y = nCenterY;
addEventListener("enterFrame", enterFrame);
function enterFrame(eventObject:Event):void {
  nRadian += 0.1;
  x = nCenterX+nRadiusX*Math.cos(nRadian);
}


[*5] EventDispatcher.addEventListener()メソッドについて詳しくは、「EventDispatcher.addEventListener()メソッド」を参照。

[*6] ActionScript 1.0/2.0では、引数が渡されても、関数に引数を設定しなければ、受取れないだけ。しかし、ActionScript 3.0では、渡されるのと同じ数の引数を関数に定義しないと、エラーが発生する。

□02 ActionScript 3.0のイベントリスナーを利用する
●フレームアクションを分割する
スクリプト003で、リスナー関数内の処理から、水平方向の座標移動により単振動させるステートメントを削除し(スクリプト004)、この処理をメインタイムラインのフレームアクションとして新たに作成する。

スクリプト004■ActionScript 3.0のMovieClipのフレームアクションを修正(as3_event_listener2.fla)

// MovieClip: アニメーションするインスタンス
// 第1フレームアクション
import flash.display.MovieClip;
import flash.events.Event;
var nCenterX:Number = stage.stageWidth/2;
var nCenterY:Number = stage.stageHeight/2;
var nRadian:Number = 0;
var nRadiusX:Number = 100;
var nRadiusY:Number = 60;
x = nCenterX;
y = nCenterY;
addEventListener(Event.ENTER_FRAME, enterFrame);
function enterFrame(eventObject:Event):void {
  nRadian += 0.1;
  // x = nCenterX+nRadiusX*Math.cos(nRadian);   →メインタイムラインへ
}

ActionScript 3.0としてのスタンダードな記述にするための修正も加えた。

(1)importステートメント
ActionScript 3.0ではクラスが、パッケージという機能により、カテゴリー分けされている。パッケージは、ディスクのフォルダ/ディレクトリと同じツリー構造になっており、ドット(.)を区切り文字としたパスで表す。

ActionScript 3.0では、MovieClipの完全パス表記(「完全修飾クラス名」)は、flash.display.MovieClip。MovieClipのプロパティやメソッドにアクセスするには、スクリプトの冒頭でimportステートメントを用いてその完全パス(完全修飾クラス名)を宣言しなければならない("enterFrame"イベントを扱うには、そのためのクラスflash.events.Eventもimportする)[*7]

(2)EventDispatcher.addEventListener()メソッドの第1引数
イベントとして文字列の"enterFrame"に替えて、Event.ENTER_FRAME定数(プロパティ)を指定した。文字列の場合、タイプミスをしてもエラーは発生せず、ただ単に動作しなくなる。Event.ENTER_FRAMEはシンタックスカラーが適用され(図002)、タイプミスがあればエラーを生じる。

図002■Event.ENTER_FRAME定数にはシンタックスカラーが適用
シンタックスカラー

つぎに、スクリプト004で削除したアニメーションの処理を、メインタイムラインのフレームアクションとして記述する。MovieClipインスタンス名は、my_mcとする。イベントリスナーを登録するターゲットはインスタンスmy_mcである(スクリプト005)。

スクリプト005■ActionScript 3.0でメインタイムラインに記述したフレームアクション(as3_event_listener2.fla)

// タイムライン: _level0
// 第1フレームアクション
import flash.display.MovieClip;
import flash.events.Event;
my_mc.addEventListener(Event.ENTER_FRAME, enterFrame);
function enterFrame(eventObject:Event):void {
  my_mc.x = my_mc.nCenterX+my_mc.nRadiusX*Math.cos(my_mc.nRadian);
}

MovieClipシンボルのスクリプト004とメインタイムラインのスクリプト005は、ふたつ合わせてスクリプト003と同じアニメーションを実現する。

[*7] importステートメントの仕様は、ActionScript 2.0とは一部変わっている。詳しくは、F-site「importの使い方が変わった」およびそこに引用した資料を参照。

●フレームアクションをクラス定義に書替える
スクリプト004と005を、ActionScript 3.0のクラス定義に書替える。クラス定義には、決まったスタイルがある(表001)。

表001■ActionScript 3.0のクラス定義
スクリプトの記述場所 外部ActionScriptファイル。
ファイル名 クラス名と同一。拡張子.as。
クラス定義 packageの中にclassを定義。
コンストラクタ関数 クラス名と同一(省略可)。
プロパティ コンストラクタ関数の前にvar宣言。型指定可能。
メソッド function定義。引数と戻り値の型指定可能。
継承 extendsキーワード。

まず、MovieClipシンボルのスクリプト004を、クラスInitializeとして定義する。新規ActionScriptファイルを開いたら、flaファイルと同じ場所にクラスと同じ名前(拡張子.as)で保存。クラスはつぎのようなスタイルで定義する。

// ActionScript 3.0クラス定義ファイル: クラス名.as
package [パッケージ名] {
  class クラス名 {
    // プロパティ(変数)宣言
    function クラス名() {   // コンストラクタ関数
      // インスタンス生成時の初期化処理
    }
    // メソッド(関数)定義
  }
}

クラスと同名の関数(function)は、「コンストラクタ関数」と呼ばれ、インスタンスが作成されるときに呼出される。したがって、関数には初期設定などの処理が記述される。クラスInitializeは、以下のように定義される(スクリプト006)。

スクリプト006■ActionScript 3.0で定義したクラスInitialize(Initialize.as)

// ActionScript 3.0クラス定義ファイル: Initialize.as
package {
  import flash.display.MovieClip;
  import flash.events.Event;
  public class Initialize extends MovieClip {
    var nCenterX:Number = stage.stageWidth/2;
    var nCenterY:Number = stage.stageHeight/2;
    var nRadian:Number = 0;
    var nRadiusX:Number = 100;
    var nRadiusY:Number = 60;
    function Initialize() {
      x = nCenterX;
      y = nCenterY;
      addEventListener(Event.ENTER_FRAME, enterFrame);
    }
    function enterFrame(eventObject:Event):void {
      nRadian += 0.1;
    }
  }
}

packageには、パッケージ名を指定しないことも可能(今回は、パッケージ名無指定とした)[*8]。クラスInitializeは、MovieClipシンボルに設定する。その場合、classには、public属性キーワードを設定する必要がある[*9]

クラスをMovieClipシンボルに設定するには、[ライブラリ]でシンボルをクリックしてから、パネルのオプションポップアップメニューから[Properties]を選択。[Symbol Properties]ダイアログボックスで[Linkage]の[Export for ActionScript]にチェックをつけて、[Class]にクラス名"Initialize"を入力する。

図003■[Symbol Properties]ダイアログボックスの[Class]にクラス名を入力

つぎに、メインタイムラインのスクリプト005を、クラスWaveXとして定義する。クラスWaveXは、イベントリスナーを利用してMovieClipインスタンスに関連づける。

クラスのインスタンスを作成するには、スクリプトでnew演算子を使ってコンストラクタ関数を呼出す。

var 変数:クラス名 = new クラス名([引数]);

クラスWaveXのコンストラクタ関数を呼出すとき、オプションの引数にMovieClipインスタンスmy_mcを渡し、その初期設定の処理内でインスタンスに対してイベントリスナーを登録。具体的には、flaファイルのメインタイムラインから、以下のようにクラスWaveXを呼出す。

var myWaveX:WaveX = new WaveX(my_mc);

スクリプト005はつぎのようにクラスWaveXとして書替えられる(スクリプト007)[*10]

スクリプト007■ActionScript 3.0で定義したクラスWaveX(WaveX.as)

// ActionScript 3.0クラス定義ファイル: WaveX.as
package {
  import flash.display.MovieClip;
  import flash.events.Event;
  class WaveX {
    var my_mc:MovieClip;
    function WaveX(target_mc) {
      my_mc = target_mc;
      my_mc.addEventListener(Event.ENTER_FRAME, enterFrame);
    }
    function enterFrame(eventObject:Event):void {
      my_mc.x = my_mc.nCenterX+my_mc.nRadiusX*Math.cos(my_mc.nRadian);
    }
  }
}

ふたつのクラスInitializeとWaveXを使って、MovieClipインスタンスに水平方向の単振動のアニメーションを行わせるには、メインタイムラインにつぎのフレームアクションを加える(スクリプト008)[*11]

スクリプト008■クラスWaveXのインスタンスを作成するメインタイムラインのフレームアクション(ActionScript3_class_1.fla)

// タイムライン: _level0
// 第1フレームアクション
var myWaveX:WaveX = new WaveX(my_mc);


[*8] packageについて、詳しくは「package定義キーワード」を参照してほしい。

[*9] classpublicについては、それぞれ「class定義キーワード」および「public属性キーワード」をご覧いただきたい。

[*10] クラスWaveXは、MovieClipシンボルに設定しないので、public属性を指定する必要はない。また、WaveX自体はMovieClipクラスを継承しなくてよい。

[*11] 実際には、WaveXのインスタンスを参照してアクセスするプロパティやメソッドは定義していないので、インスタンスを格納する左辺の変数はなくてもよい。

new WaveX(my_mc);

●イベントリスナーに加えるクラスを増やしてみる
スクリプト007のクラスWaveXをひな形にして、イベントリスナーに加わるクラスを、あと3つ追加定義する。第1は、MovieClipインスタンスに垂直方向に単振動のアニメーションをさせるクラスWaveYだ(スクリプト009)[*12]

スクリプト009■ActionScript 3.0で定義したクラスWaveY(WaveY.as)

// ActionScript 3.0クラス定義ファイル: WaveY.as
package {
  import flash.display.MovieClip;
  import flash.events.Event;
  class WaveY {
    var my_mc:MovieClip;
    function WaveY(target_mc) {
      my_mc = target_mc;
      my_mc.addEventListener(Event.ENTER_FRAME, enterFrame);
    }
    function enterFrame(eventObject:Event):void {
      my_mc.y = my_mc.nCenterY+my_mc.nRadiusY*Math.sin(my_mc.nRadian);
    }
  }
}

第2のクラスDirectionXは、MovieClipインスタンスの水平方向の位置によって、向きと幅を変える(幅は中央で実寸、両端では0にする)。幅の変更には、DisplayObject.scaleXプロパティを使った(スクリプト010)[*13]

スクリプト010■ActionScript 3.0で定義したクラスDirectionX(DirectionX.as)

// ActionScript 3.0クラス定義ファイル: DirectionX.as
package {
  import flash.display.MovieClip;
  import flash.events.Event;
  class DirectionX {
    var my_mc:MovieClip;
    function DirectionX(target_mc) {
      my_mc = target_mc;
      my_mc.addEventListener(Event.ENTER_FRAME, enterFrame);
    }
    function enterFrame(eventObject:Event):void {
      my_mc.scaleX = -Math.sin(my_mc.nRadian);
    }
  }
}

第3のクラスDirectionYは、Flash 8から実装されたBlurFilterクラスを使って、MovieClipインスタンスの垂直方向の位置によって、ぼかしを加えることにする(上にいくほど強く、下にいくほど弱くする)。BlurFilterクラスのコンストラクタ関数に渡すふたつの数値は、それぞれX軸およびY軸方向のぼけ幅を指定する。BlurFilterインスタンスは、配列に格納したうえでMovieClip.filtersプロパティに設定する(スクリプト011)[*14]

スクリプト011■ActionScript 3.0で定義したクラスDirectionY(DirectionY.as)

// ActionScript 3.0クラス定義ファイル: DirectionY.as
package {
  import flash.display.MovieClip;
  import flash.events.Event;
  import flash.filters.BlurFilter;
  class DirectionY {
    var my_mc:MovieClip;
    function DirectionY(target_mc) {
      my_mc = target_mc;
      my_mc.addEventListener(Event.ENTER_FRAME, enterFrame);
    }
    function enterFrame(eventObject:Event):void {
      var nBlur:Number = -(Math.sin(my_mc.nRadian)-1);
      var myBlur:BlurFilter = new BlurFilter(nBlur*4, nBlur);
      my_mc.filters = [myBlur];
    }
  }
}

スクリプト009から011までの3つのクラスのアニメーション処理をMovieClipインスタンスmy_mcに適用するには、メインタイムラインのフレームアクション(スクリプト008)に同じ要領でステートメントを追加する(スクリプト012)。

スクリプト012■クラスWaveXのインスタンスを作成するメインタイムラインのフレームアクション(ActionScript3_class_2.fla)

// タイムライン: _level0
// 第1フレームアクション
var myWaveX:WaveX = new WaveX(my_mc);
var myWaveY:WaveY = new WaveY(my_mc);
var myDirectionX:DirectionX = new DirectionX(my_mc);
var myDirectionY:DirectionY = new DirectionY(my_mc);

4つの独立したクラスによるイベントリスナーの処理が組合わさることにより、楕円運動に水平方向の伸縮と垂直方向に比例したぼけが適用され、3D風に回転するアニメーションが実現される(図004)。

図004■4つのイベントリスナーを利用した3D風回転アニメーション

ひとつのインスタンスの同じイベントに対して複数のリスナーを適用することにより、複数のスクリプトで連携して処理したり、あるいはそれぞれが特定の処理を専門的に行うこともできる。イベントリスナーを活用すれば、大規模なプロジェクトや複雑な処理を、適切な単位に小分けした設計が可能になる。

[*12] X軸方向の単振動をcos、Y方向の単振動をsinで定義して同期させると、楕円運動になる。なお、「はじめの一歩のアクションスクリプト」「4. Mathクラスを使う」参照。

[*13] DisplayObject.scaleXプロパティも、MovieClip._xscaleと同じく、マイナス値は水平方向の向きを反転させる。スクリプト010で、Math.sin()の戻り値にマイナスをつけているのは、もとのMovieClipインスタンスが右向きのためである。

[*14] スクリプトによるフィルタの適用については、「新機能とスクリプティング」「1. ぼかしとドロップシャドウフィルタ」参照。

□03 ActionScript 3.0のマウスイベント
●MouseEvent.CLIKイベント
マウスイベントは、MouseEventクラスに定められている[*15]。MouseEventクラスのイベントは、ActionScript 1.0/2.0におけるMovieClipのイベントとは、その名称も発生する仕様も少し異なっているので注意。

まず、MovieClip.onReleaseに相当するMouseクラスのイベントは、MouseEvent.CLICK。以下に定義するクラスMyButton(スクリプト013)をMovieClipシンボルに設定すると、インスタンスをクリックしたとき、つぎのような出力が[Output]パネルに表示される[*16]

[object MyButton] clicked
スクリプト013■マウスクリックを受取るクラスMyButton

// ActionScript 3.0クラス定義ファイル: MyButton.as
package {
  import flash.display.MovieClip;
  import flash.events.MouseEvent;
  public class MyButton extends MovieClip {
    function MyButton() {
      addEventListener(MouseEvent.CLICK, click);
    }
    function click(eventObject:MouseEvent):void {
      trace(this, "clicked");
    }
  }
}

ActionScript 3.0のMouseEvent.CLIKで指定されるイベントは、1.0/2.0のMovieClip.onReleaseと同じ。1.0/2.0のMovieClip.onPressに相当する3.0のマウスイベントは、MouseEvent.MOUSE_DOWNになる(スクリプト014)。。

スクリプト014■マウスのプレスとリリースを受取るクラスMyButton

// ActionScript 3.0クラス定義ファイル: MyButton.as
package {
  import flash.display.MovieClip;
  import flash.events.MouseEvent;
  public class MyButton extends MovieClip {
    function MyButton() {
      addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
      addEventListener(MouseEvent.CLICK, click);
    }
    function mouseDown(eventObject:MouseEvent):void {
      trace(this, "pressed");
    }
    function click(eventObject:MouseEvent):void {
      trace(this, "clicked");
    }
  }
}

[*15] 厳密にはマウスイベントはMovieClipが継承するInteractiveObjectクラスに定義されており、MouseEventクラスはそのイベントを指定する文字列の定数を定める。詳しくは、「マウスイベント」を参照されたい。

[*16] ActionScript 3.0のtrace()関数は、1.0/2.0から仕様が拡張され、複数の引数を指定できる。

●イベントハンドラメソッドの実装
ActionScript 3.0のMovieClipには、MovieClip.onReleaseなどのイベントハンドラメソッドを設定することができない。カスタムクラスなら、onPressやonReleaseなどのメソッドを自由に定義することができる。スクリプト004のMyButtonクラスを修正する。

まず、onPressやonReleaseに値(コールバック関数)を設定できるようにするためには、これらをプロパティとして宣言する。そして、コールバック関数が定義されたら、マウスイベントに応じてそれらの関数を呼出さなければならない(スクリプト015)。なお、onPressやonReleaseは、インスタンスの外部から設定することになるので、Public属性を指定する。

スクリプト015■イベントハンドラメソッドを実装したクラスMyButton

// ActionScript 3.0クラス定義ファイル: MyButton.as
package {
  import flash.display.MovieClip;
  import flash.events.MouseEvent;
  public class MyButton extends MovieClip {
    public var onPress:Function;
    public var onRelease:Function;
    function MyButton() {
      addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
      addEventListener(MouseEvent.CLICK, click);
    }
    function mouseDown(eventObject:MouseEvent):void {
      onPress();
    }
    function click(eventObject:MouseEvent):void {
      onRelease();
    }
  }
}

スクリプト015のクラスMyButtonを試すには、クラスを設定したインスタンスが配置されているタイムラインに、たとえばつぎのようなフレームアクションを記述する(スクリプト016)。インスタンス上でマウスボタンのプレス・リリースを行うと、[Output]パネルにtrace()関数の出力が表示される。

スクリプト016■クラスMyButtonをテストするためのフレームアクション

// タイムライン: _level0
// フレームアクション
my_mc.onPress = function() {
  trace("press");
};
my_mc.onRelease = function() {
  trace("release");
};

●onReleaseOutsideイベントの実装
ActionScript 3.0のマウスイベントの構成は、1.0/2.0とは少し異なっている。たとえば、MouseEventクラスには、ダブルクリックを指定するMouseEvent.DOUBLE_CLICKがある[*17]

ところが逆に、ActionScript 1.0/2.0のMovieClip.onReleaseOutsideに相当するイベントがない。ただ、onReleaseOutsideをスクリプトで扱えるようにすることは可能だ。先に定義したスクリプト015のMyButtonクラスにonReleaseイベントハンドラメソッドが設定できるようにしてみる。

第1に、インスタンスの外でマウスボタンを放したというイベントの取得である。ActionScript 3.0では、Stageに対してイベントリスナーを登録することができる。インスタンスの外のマウスイベントは、Stageに対して発生する。

第2に、onReleaseOutsideイベントの捉え方だ。この処理を扱うには、マウスボタンのプレスとリリースを組合わせて捉えるMouseEvent.CLICKより、リリースのみを受取るMouseEvent.MOUSE_UPMouseEvent.MOUSE_DOWNにより、それぞれの操作を個別に扱った方が構成しやすい。

まずMouseEvent.MOUSE_DOWNのイベントが発生したとき、インスタンスとStageに対してMosueEvent.MOUSE_UPのイベントリスナーをそれぞれ登録する。するとその後、インスタンスのイベントリスナー関数が呼出されればonRelease、Stageのイベントリスナー関数が呼出されればonReleaseOutsideと判別できる。マウスボタンが放されたら、イベントリスナーは忘れずに削除する。削除のメソッドはEventDispatcher.removeEventListener()で、シンタックスはつぎのとおりだ。

[ターゲットインスタンス].removeEventListener(イベント, リスナー関数)

上述の処理を加えたクラスMyButtonが、以下のスクリプト017である[*18]

スクリプト017■onReleaseOutsideイベントハンドラメソッドを追加したクラスMyButton(MyButton.as)

// ActionScript 3.0クラス定義ファイル: MyButton.as
package {
  import flash.display.MovieClip;
  import flash.events.MouseEvent;
  public class MyButton extends MovieClip {
    public var onPress:Function;
    public var onRelease:Function;
    public var onReleaseOutside:Function;
    function MyButton() {
      addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
    }
    function mouseDown(eventObject:MouseEvent):void {
      onPress();
      addEventListener(MouseEvent.MOUSE_UP, mouseUp);
      stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp2);
    }
    function mouseUp(eventObject:MouseEvent):void {
      onRelease();
      removeEventListener(MouseEvent.MOUSE_UP, mouseUp);
      stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp2);
    }
    function mouseUp2(eventObject:MouseEvent):void {
      onReleaseOutside();
      removeEventListener(MouseEvent.MOUSE_UP, mouseUp);
      stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUp2);
    }
  }
}

上記スクリプト017のクラスMyButtonをテストするには、スクリプト016のフレームアニメーションにonReleaseOutsideメソッドの設定を加える(スクリプト018)。

スクリプト018■修正したクラスMyButtonをテストするためのフレームアクション(as3_button.fla)

// タイムライン: _level0
// フレームアクション
my_mc.onPress = function() {
  trace("press");
};
my_mc.onRelease = function() {
  trace("release");
};
my_mc.onReleaseOutside = function() {
  trace("releaseOutside");
};


[*17] MouseEvent.DOUBLE_CLICKの扱いについては、F-site「doubleClickを受取る」を参照。

[*18] このクラスMyButtonの定義は、マウスイベントの扱いを示すための最小限のサンプルである。たとえば、テスト用のスクリプト018で、イベントハンドラメソッドのいずれかが設定されてない場合、クラスのメソッドから呼出す関数が存在しない旨のエラーになる。こうした対処も施したサンプルは、「EventDispatcher.addEventListener()メソッド」のスクリプト001になる。

●ActionScript 3.0のメリット
Flash 9 ActionScript 3.0 Previewは、まだパブリックアルファの段階なので、たとえばonReleaseOutsideに相当するマウスイベントも実装されるかもしれない。しかし、実装されなかったとしても、おそらく高い確率で、こうした不足を補うクラスが、次期Flashオーサリングツールに同梱されて出荷されると思われる。あるいは、誰かが追加のクラスを書いて、公開するかもしれない。実は、これがActionScript 3.0を使う、隠れた大きなメリットである。

ActionScript 3.0は、Flash Player 9で新たに開発された専用の仮想マシンAVM(ActionScript Virtual Machine) 2で動作するため、処理がきわめて高速になる。しかし、それはおもにスクリプトに関わる処理についてのことだ。描画やテキスト、サウンドなどの処理は、ActionScript 1.0/2.0が動作するAVM1と共通である[*19]

つまり、その共通部分のエンジンは、従来のFlash Playerの設計をベースにした改善が加えられているのであって、根本的な変更はない。したがって、多くのビジュアル表現を主体にしたFlashコンテンツでは、ActionScript 3.0により処理速度が明らかに変わってくる例は、それほど多くはないと思われる。

むしろ、ビジュアル表現の処理速度より、開発したクラスの処理がActionScript定義済みのクラスと遜色ない速度で行われることの意味が大きい。これにより、クラスを作成し、さらに汎用化して、公開するという意欲が高まる。

たとえば、XMLや文字列を処理するユーティリティ的なクラスや、3次元座標を扱うクラスなどは、世界中の誰かが開発し公開する可能性は少なくない。そうなれば、それらをFlashアプリケーションに追加しさえすれば、ActionScript定義済みクラスと同じ感覚で、それらのクラスが利用できる。

ActionScript 3.0は、クラスを開発する環境を向上させるだけでなく、それらの資産を共有したり利用する環境も大きく拡げてくれることが期待される。

[*19] 前出注[*1]の記事のほか、「ActionScript 3デビューセミナー - その真価を探る」(06/7/28)を参考にしてほしい。


作成者: 野中文雄
作成日: 2006年9月25日


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