○01. rootプロパティでメインタイムラインの関数にアクセスできない
rootプロパティは、DisplayObjectクラスに定義されており、それをMovieClipクラスが継承する。DisplayObjectクラスは、MovieClipと異なりダイナミック(dynamic)なクラスではないので、クラスに定義されていないメンバ(プロパティおよびメソッド)にアクセスしようとすると、静的な型チェックによりコンパイルエラーが生じる。
スクリプト001■メインタイムラインの関数をroot参照つきで呼出す
// メインタイムライン
// フレームアクション
function xTest():void {
trace(this);
}
root.xTest(); // コンパイルエラー
// MovieClip(root).xTest(); // MovieClipにキャスト |
たとえば、上記スクリプト001を[ムービープレビュー]で実行すると、つぎのような[コンパイルエラー]が表示される。
1061: 未定義である可能性のあるメソッド xTest を、静的型 flash.display:DisplayObject の参照を使用して呼び出しました。
●対応1: [strictモード]を解除する
デフォルトの[strictモード]を解除してstandardモードにすれば(図001)、ランタイムではエラーは生じない。
図001■[ActionScript 3.0設定]ダイアログボックスで[strictモード]を解除
●対応2: MovieClipにキャストする
データ型を明示的にキャストして、MovieClipに変換する。上記スクリプト001で、コンパイルエラーの出るステートメントをコメントアウトし、つぎの行のコメントアウトを外すと、[strictモード]でもエラーなく動作する。
なお、ActionScript 3.0で実装されたas演算子を用いると、2.0ではできなかった配列のキャストが可能になる。
○02. ビットマップをダイナミックに配置する
[ライブラリ]のビットマップをダイナミックにタイムラインに配置することは、Flash 8/ActionScript 2.0から可能になった(Flash 8特別セミナー「新機能とスクリプティング」「2. ビットマップデータをディゾルブする」参照)。
まず、[ライブラリ]のビットマップには、[リンケージ]でクラスを指定する(図002)。ActionScript 3.0では、クラス名が識別子の役割を果たす。指定したクラスが定義されていなければ、BitmapDataクラスを継承した空の新規クラスが自動的に生成される(図003)。
図002■[リンケージプロパティ]ダイアログボックス
図003■クラスを自動生成するかどうかの確認
つぎに、ActionScript 3.0では、2.0のように特殊なメソッドを使うことなく、インスタンスの生成はnew演算子でコンストラクタを呼出して行う。そして、ステージ上に表示するには、タイムラインのディスプレイ(表示)リストにインスタンスを追加すればよい(スクリプト002)。
スクリプト002■ビットマップをダイナミックに配置する
// フレームアクション
// クラスのimport
import flash.display.BitmapData;
import flash.display.Bitmap;
// ビットマップからBitmapDataインスタンスを生成
var myBitmapData:BitmapData = new Pen(0, 0);
// BitmapDataを用いてBitmapインスタンスを生成
var myBitmap:Bitmap = new Bitmap(myBitmapData);
// タイムラインのディスプレイリストに追加
addChild(myBitmap);
trace(this.getChildIndex(myBitmap)); // 出力: 0
|
なお、ActionScript 3.0は、2.0とは「importの使い方が変わった」ことに注意する必要がある。
○03. イベントの扱い
ActionScript 2.0/1.0では、インスタンスに記述するon()やonClipEvent()イベントハンドラアクションを別にしても、イベントの扱いにはイベントハンドラメソッドやイベントリスナーが存在し、コンポーネントのイベントリスナーもActionScript定義済みのものとはシンタックスが異なる(スクリプト003)。
スクリプト003■ActionScript 2.0のイベントの扱い
// インスタンスの型指定
var myButton:mx.controls.Button;
var my_txt:TextField;
// 初期値設定
// TextField: my_txtを配置
var nRadian:Number = 0;
// リスナーオブジェクト生成
var oListener:Object = new Object();
// ボタンMovieClip
button_mc.onRelease = function():Void {
my_mc.onEnterFrame = xAnimate;
};
function xAnimate():Void {
this._xscale = Math.cos(nRadian += 0.1)*100;
}
// Buttonコンポーネント
myButton.addEventListener("click", oListener);
oListener.click = function():Void {
delete my_mc.onEnterFrame;
};
// Keyリスナー設定
Key.addListener(oListener);
oListener.onKeyDown = function():Void {
var nKey = Key.getCode();
my_txt.text = nKey;
};
|
ActionScript 3.0では、イベントはイベントリスナーで扱うことが原則になる。EventDispatcher.addEventListener()メソッドに、引数としてイベントとリスナー関数を指定する(スクリプト004。なお、「ActionScript 3.0書き方教室」「ActionScript 3.0の最小限のフレームアクション」参照)。
スクリプト004■ActionScript 3.0のイベントの扱い
// 初期値設定
// TextField: my_txtを配置
var nRadian:Number = 0;
// ボタンMovieClip
button_mc.addEventListener(MouseEvent.CLICK, xRelease);
function xRelease(eventObject:MouseEvent):void {
my_mc.addEventListener(Event.ENTER_FRAME, xAnimate);
}
function xAnimate(eventObject:Event):void {
my_mc.scaleX = Math.cos(nRadian += 0.1);
}
// Buttonコンポーネント
myButton.addEventListener(MouseEvent.CLICK, xClick);
function xClick(eventObject:MouseEvent):void {
my_mc.removeEventListener(Event.ENTER_FRAME, xAnimate);
}
// Keyリスナー設定
stage.addEventListener(KeyboardEvent.KEY_DOWN, xKeyDown);
function xKeyDown(eventObject:KeyboardEvent):void {
var nKey:int = eventObject.keyCode;
my_txt.text = nKey.toString();
}
|
ActionScript 2.0のバージョン2コンポーネントアーキテクチャにおけるEventDispatcher.addEventListener()メソッドとほぼ同じシンタックス。ただし、イベントリスナーにはオブジェクトでなく関数を指定する。
リスナー関数には、イベントオブジェクトが引数として渡される。ActionScript 2.0/1.0と異なり、引数を受取らないとエラーが発生する。また、戻り値なしの型指定には、頭文字が大文字でなく小文字のvoidを用いる。
なお、flaファィルに記述するフレームアクションでは、タイムラインに予め配置されたインスタンスは、自動的に認識される。その反面、明示的に型指定することができない。クラスでは、[パブリッシュ設定]の[ActionScript 3.0設定]で[ステージのインスタンスを自動宣言]を解除することによって、インスタンスの明示的な型指定が可能になる。
○04. MovieClipのボタンをつくる
Flash CS3/ActionScript 3.0でも、2.0と同じくフレームラベルとして"_up"と"_over"、"_down"を設定すれば、ボタンのアニメーションを簡単に実現することができる(図004)。ただし、フレームアクションに2.0の場合と異なるステートメントを1行追加する必要がある。ボタンのMovieClipインスタンスのSprite.buttonModeプロパティをtrueに設定することだ。
図004■MovieClipにフレームラベルとフレームアクションを設定
たとえば、ボタンのMovieClipシンボルのフレームアクションに、つぎのステートメントを加える。これにより、ボタンのアニメーションが動作し、マウスポインタが指差しカーソルに変わる(図004)。
buttonMode = true;
ヒット領域をMovieClip(またはSprite)インスタンスで作成し、Sprite.hitAreaプロパティに設定するのも、ActionScript 2.0と基本的に同じである(スクリプト005)。ただし、MovieClipまたはSpriteインスタンスを内包すると、デフォルトではそのインスタンスが最初のマウスイベントを受取ってしまうため、ボタンのアニメーションが実行されなくなる(ただし、マウスイベントそのものは受取れる[*1])。
スクリプト005■ヒット領域を設定したボタンMovieClipのフレームアクション
// タイムライン: ボタンのMovieClip
// 第1フレームアクション
buttonMode = true;
hitArea = hitArea_mc;
hitArea_mc.visible = false;
stop();
|
ボタンのアニメーションを動作させるためには、内包したMovieClipまたはSpriteインスタンスのInteractiveObject.mouseEnabledプロパティをfalseに設定する必要がある。たとえば、内包されるMovieClipシンボルのフレームアクションにつぎのスクリプト006を設定する。
スクリプト006■ボタンのMovieClipシンボルに内包されるMovieClipに設定するフレームアクション
// ボタンのMovieClipシンボル内に配置されたMovieClip
// 第1フレームアクション
mouseEnabled = false;
|
[*1] ボタンのMovieClipインスタンスにマウスイベントのリスナー関数を設定した場合、リスナー関数が受取る引数のイベントオブジェクトで、イベントに関わるインスタンスの情報が得られる。
ボタンのMovieClipシンボルに内包したMovieClipインスタンスのInteractiveObject.mouseEnabledプロパティの設定により、MouseEvent.targetプロパティの返す値が変わる。その内包されたインスタンスをクリックしたとき、InteractiveObject.mouseEnabledプロパティをfalseに設定していないと、その内包されたインスタンスの参照が返される。他方、falseに設定していると、ボタンのMovieClipインスタンスの参照が返されることになる。
なお、MouseEvent.currentTargetプロパティは、内包されたMovieClipのInteractiveObject.mouseEnabledプロパティの設定にかかわらず、イベントリスナーが登録されたボタンのMovieClipインスタンスの参照を返す。
|
○05. イベントハンドラメソッドを実装するクラス定義
ActionScript 3.0のマウスイベントには、2.0/1.0のMovieClip.onReleaseOutsideに相当するイベントがない[*2]。そのため、InteractiveObject.mouseDown(イベント定数MouseEvent.MOUSE_DOWN)およびInteractiveObject.mouseUp(イベント定数MouseEvent.MOUSE_UP)のイベントリスナーを組合わせて、処理を記述する必要がある[*3]。
●マウスイベントを処理するクラス
ActionScript 3.0のクラス定義は、基本的に以下のスタイルを採る。2.0との違いは、第1にclass定義のコードブロック全体を、package定義キーワードで括る必要がある。第2に、コンストラクタにはpublic属性しか指定できない(public属性キーワードは省略可能)[*4]。
// ActionScript 3.0クラス定義ファイル: クラス名.as
package [パッケージ名] {
class クラス名 {
// プロパティ(変数)宣言
public function クラス名() {
// インスタンス生成時の初期化処理
}
// メソッド(関数)定義
}
}
つぎのスクリプト007は、ボタンのMovieClipシンボルの[クラス]に設定して、ActionScript 2.0のMovieClip.onPressとMovieClip.onRelease、MovieClip.onReleaseOutsideイベントに対応した処理を行う。なお、MoiveClipシンボルに設定するclassは、public属性を指定する必要がある[*5]。
スクリプト007■onPress/onRelease/onReleaseOutsideに対応するイベントを処理するクラス
// ActionScript 3.0クラス定義ファイル: MyButton.as
// ボタンのMovieClipシンボルの[クラス]に設定
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
public class MyButton extends MovieClip {
public function MyButton() {
addEventListener(MouseEvent.MOUSE_DOWN, press);
}
private function press(eventObject:MouseEvent):void {
trace("press");
addEventListener(MouseEvent.MOUSE_UP, release);
stage.addEventListener(MouseEvent.MOUSE_UP, releaseOutside);
}
private function release(eventObject:MouseEvent):void {
trace("release");
removeEventListener(MouseEvent.MOUSE_UP, release);
stage.removeEventListener(MouseEvent.MOUSE_UP, releaseOutside);
}
private function releaseOutside(eventObject:MouseEvent):void {
trace("releaseOutside");
removeEventListener(MouseEvent.MOUSE_UP, release);
stage.removeEventListener(MouseEvent.MOUSE_UP, releaseOutside);
}
}
}
|
まず、ボタンのMovieClipインスタンスに対して、MouseEvent.MOUSE_DOWNイベントのリスナー関数を登録する。すると、インスタンス上でマウスボタンを押したときに、そのリスナー関数が呼出される。
つぎに、MouseEvent.MOUSE_DOWNイベントのリスナー関数内では、MouseEvent.MOUSE_UPイベントのリスナー関数を、ボタンのMovieClipインスタンスとステージ(DisplayObject.stageプロパティで参照)に対してそれぞれ登録する。これにより、マウスボタンをインスタンス上で放したときは前者、インスタンス外で放したときは後者のリスナー関数が呼出される。すなわち、ActionScript 2.0のMovieClip.onReleaseとMovieClip.onReelaseOutsideイベントに相当する処理を行うことができる。
●イベントハンドラメソッドを実装するクラス
前述スクリプト007にイベントハンドラメソッドを実装するには、ふたつの処理を加えればよい。
第1は、ユーザーがコールバック関数を設定できるように、イベントハンドラメソッドをプロパティ宣言することだ。関数は、Function型で指定する。第2は、それぞれのイベントが発生したときに、対応するイベントハンドラメソッド(コールバック関数)を呼出すことである。
以下のスクリプト008をボタンのMovieClipシンボルに[クラス]として設定すると、そのインスタンスにonPress/onRelease/onReleaseOutsideイベントハンドラメソッドを、たとえばタイムラインからつぎのように設定できるようになる[*6]。なお、インスタンス名をbutton_mcとした。
// タイムライン: ボタンのMovieClipインスタンスbutton_mcを配置
// フレームアクション
button_mc.onPress = function():void {
trace("press");
};
button_mc.onRelease = function():void {
trace("release");
};
button_mc.onReleaseOutside = function():void {
trace("releaseOutside");
};
スクリプト008■イベントハンドラメソッドを実装したクラス
// ActionScript 3.0クラス定義ファイル: MyButton.as
// ボタンのMovieClipシンボルの[クラス]に設定
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;
public function MyButton() {
addEventListener(MouseEvent.MOUSE_DOWN, press);
}
private function press(eventObject:MouseEvent):void {
// trace("press");
onPress();
addEventListener(MouseEvent.MOUSE_UP, release);
stage.addEventListener(MouseEvent.MOUSE_UP, releaseOutside);
}
private function release(eventObject:MouseEvent):void {
// trace("release");
onRelease();
removeEventListener(MouseEvent.MOUSE_UP, release);
stage.removeEventListener(MouseEvent.MOUSE_UP, releaseOutside);
}
private function releaseOutside(eventObject:MouseEvent):void {
// trace("releaseOutside");
onReleaseOutside();
removeEventListener(MouseEvent.MOUSE_UP, release);
stage.removeEventListener(MouseEvent.MOUSE_UP, releaseOutside);
}
}
}
|
[*2] 他方、ActionScript 3.0では、ダブルクリックをイベントとして受取ることができる。詳しくは、F-site「doubleClickを受取る」参照。
[*3]「Flash 9 ActionScript 3.0 Previewのイベントリスナーとクラス定義」の「03 ActionScript 3.0のマウスイベント」参照。
[*4] ActionScript 3.0では、クラスやプロパティ・メソッドに対するアクセス制御の指定が、2.0の2つから4つに増えた。デフォルト(グレー表示)が同じパッケージ内からのアクセスを許すinternalになったり、privateの仕様が変わるなど、2.0とは異なる部分がある。
アクセス制御の属性 |
ActionScript 3.0 |
ActionScript 2.0 |
同一クラス内 |
サブクラス |
同一パッケージ内 |
すべてのクラス |
同一クラス内 |
サブクラス |
同一パッケージ内 |
すべてのクラス |
private |
○ |
× |
× |
× |
○ |
○ |
× |
× |
protected |
○ |
○ |
× |
× |
− |
internal |
○ |
× |
○ |
× |
− |
public |
○ |
○ |
○ |
○ |
○ |
○ |
○ |
○ |
[*5] コンストラクタにprivate属性が指定できないと、たとえばSingletonパターンの実装にひと工夫必要になる。Singletonパターンの実装例については、「ActionScript 3.0でプライベートなコンストラクタを定義する」参照。
[*6] スクリプト008では、クラスでイベントハンドラメソッド用に宣言したインスタンスプロパティにコールバック関数が設定されていないと、ランタイムエラーが発生する。コールバック関数が設定されているかどうかの判定を加え、より整理したサンプルは、「EventDispatcher.addEventListener()メソッド」の[訳者注*3]を参照。
|
_____
作成者: 野中文雄
作成日: 2005年7月21日