サイトトップ

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

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

TLFテキストが配置されたメインタイムラインの初期化

ID: FN1108001 Product: Flash CS5 and CS5.5 Platform: All Version: 10 and above/ActionScript 3.0

[TLFテキスト]で使われるActionScriptライブラリは、デフォルトではランタイム共有ライブラリとして読込まれます[*1]。そのため、[TLFテキスト]を用いたSWFファイル本体は容量が小さく抑えられるものの、ライブラリのロードに少し時間がかかったり、初期化される間にメインタイムラインが密かに表示リスト間をさまよったりします[*2]。しかも、そのふるまいが、Flash Player 10や10.1(Flash Professional CS5)と10.2(同CS5.5)とでは異なることに、注意しなければなりません。

[*1] [TLFテキスト]が使われたムービーのパブリッシュについては「TLFテキストを含むSWFファイルのパブリッシュ」をご参照ください。

[*2] Flashcoders「TLF: Questions... My situation... Your thoughts?」(Henrik Andersson)が、ランタイム共有ライブラリを用いたTLF(Text Layout Framework)コンポーネントライブラリの読込みについて、簡単に説明しています(英文)。デフォルトでは、メインタイムラインを一旦プリローダに入れて切離し、ライブラリを読込んでから本来の位置に戻します(後述参照)。


01 メインタイムラインはどこにいるのか
メインタイムラインは普通ステージ(Stageオブジェクト)の表示リストに初めの子インスタンスとして加わります。いわばStageオブジェクトの第一子です(図001)。

図001■メインタイムラインは普通Stageオブジェクトの最初の子
ステージ
(Stageオブジェクト)
|
メインタイムライン
(MovieClipインスタンス)

ところが、タイムラインの(表示リストの)階層のどこかに[TLFテキスト]があると、ステージとメインタイムラインとのつながりが変わります。たとえば、Flash Professional CS5で、新たなムービーのメインタイムラインに[TLFテキスト]をひとつ置いてみます(図002)。

図002■メインタイムラインに[TLFテキスト]を置く

そして、メインタイムラインにはつぎのフレームアクションを書きます(図003)。メインタイムラインからwhileループによりDisplayObject.parentプロパティで親インスタンスを順に遡って、配列エレメントに加えたうえで[出力]します。

var parents:Array = [];
var myParent:DisplayObjectContainer = parent;
parents.push(this);
while (myParent) {
  parents.push(myParent);
  myParent = myParent.parent;
}
trace(parents);

図003■メインタイムラインのフレームアクションで親インスタンスを遡って確かめる

[出力]された配列エレメントは、以下のようにメインタイムライン([object MainTimeline])から始まり、表示リストの階層の頂点であるStageオブジェクト([object Stage])で終わっています。注目したいのは、ふたつの間にLoaderオブジェクト([object Loader])とプリローダインスタンス([object MainTimeline__Preloader__])が加わっていることです(図004)。

[object MainTimeline],[object Loader],[object MainTimeline__Preloader__],[object Stage]
図004■Flash CS5で[TLFテキスト]をもったメインタイムラインの場所
ステージ
(Stageオブジェクト)
|
プリローダ
(MovieClipインスタンス)
|
Loaderオブジェクト
|
メインタイムライン
(MovieClipインスタンス)

ところが、同じムービーをFlash CS5.5でつくり、その最新バージョンであるFlash Player 10.2で[ムービープレビュー]すると、[出力]はつぎのようになります。これは、前掲図001の普通の場合と同じ状態を示します。

[object MainTimeline],[object Stage]

もっとも、もう少し詳しく調べると、Flash Player 10.2ではメインタイムラインがStageオブジェクトの第二子になっています(後述03)。そして、いずれのバージョンでもこれらのつながりは一時的で、最後には普通の状態に落着きます。そこで、[TLFテキスト]を含んだメインタイムラインとStageオブジェクトのつながりがどう移り変わるか、ふたつのバージョンそれぞれについてご説明します。


02 Flash Player 10および10.1における[TLFテキスト]をもったメインタイムラインの動き
Flash Professional CS5つまりFlash Player 10または10.1でムービーの中に[TLFテキスト]を置くと、メインタイムラインの(MovieClip)インスタンスは図005のように表示リストの間をさまよいます。

図005■Flash CS5で[TLFテキスト]をもったメインタイムラインのふるまい
[1]
メインタイムライン

[2]
Stageオブジェクト
|
プリローダ
|
Loaderオブジェクト
|
メインタイムライン

[3]
Stageオブジェクト
|
メインタイムライン
インデックス0
|
プリローダ
インデックス1

[4]
Stageオブジェクト
|
メインタイムライン

[1]まず、メインタイムラインのインスタンスがつくられるとき、いずれの表示リストにも属しません。つまり、親のないインスタンスとして生まれます。

[2]つぎに、前項で見たように、メインタイムラインはLoaderオブジェクトの子になり、プリローダのインスタンスを介して、Stageオブジェクトの表示リストに加わります。

[3]その後、Loaderオブジェクトからメインタイムラインは引取られて、Stageオブジェクトの実子になります。

[4]最後に、プリローダが消し去られると、ようやくStageオブジェクトとタイムラインは親ひとり子ひとりの普通の関係に落着くのです。この状態に至れば、[TLFテキスト]があることをとくに気にかける必要はありません。

スクリプトを書くときに気をつけなければならない例を、[1]から[3]について考えてみます。

Flashムービー(FLA)ファイルにドキュメントクラスを設定した場合(図006)、そのコンストラクタメソッドは[1]のときに呼出されます。このとき、プロパティDisplayObject.parentDisplayObject.stageの値はnullです。したがって、コンストラクタメソッドからStageオブジェクトのプロパティ、たとえばステージの幅や高さ(Stage.width/Stage.heightプロパティ)を調べようとすれば、ランタイムエラー#1009が告げられます[*3]

TypeError: Error #1009: nullのオブジェクト参照のプロパティまたはメソッドにアクセスすることはできません。

図006■ムービーにドキュメントクラスを設定する

メインタイムラインの第1フレームアクションは、前項で確かめたとおり[2]のときに実行されます。このとき、親インスタンス(DisplayObject.parentプロパティ)はLoaderオブジェクト、Stageオブジェクトのインデックス0の子(stage.getChildAt(0))はプリローダになります。普通は、前者がStageオブジェクト、後者はメインタイムラインが参照されるのと異なります。もっとも、このような参照の仕方はあまり多く用いられないでしょう。

[2]で起こる問題の例として、もうひとつ「TLFテキストのある外部SWFを読込むとその中のオブジェクトにアクセスできない」場合があります。詳しくは、リンクしたノートをお読みください。

[3]はStageオブジェクトの子にプリローダが残っているだけですので、一見問題なさそうです。しかし、[2]から[3]に移るときメインタイムライン上のインスタンスにDisplayObject.removedFromStageDisplayObject.addedToStageイベントが生じることに注意しなければなりません。

たとえば、メインタイムラインの第1フレームに置いたMovieClipシンボルにDisplayObject.removedFromStageイベント(定数Event.REMOVED_FROM_STAGE)のリスナー関数を定め、インスタンスがステージから削除されたときの後かたづけをする場合が考えられます(図007)[*4]。つぎのようなテスト用のフレームアクションを書いてみます。

addEventListener(Event.REMOVED_FROM_STAGE, xRemove);
function xRemove(eventObject:Event):void {
  // ステージから消すときの後かたづけ処理
  alpha = 0.5;   // テスト用
}

図007■DisplayObject.removedFromStageイベントリスナーに後かたづけの処理を定める

ムービーが[TLFテキスト]を含まなければ、DisplayObjectContainer.removeChild()メソッドでインスタンスを親タイムラインの表示リストから除いたとき、リスナー関数が呼出されます。これが本来期待する動きです。ところが、ムービー内に[TLFテキスト]を置くと、たちまちこの期待が裏切られます。

たとえば、先ほどフレームアクションを設定した前掲図007のMovieClipシンボルに、[TLFテキスト]をひとつ置いてみます(図008左図)。すると、[2]から[3]に移るときDisplayObject.removedFromStageイベントが起こるため、[4]の普通の状態になったときには、イベントリスナーが呼出されてしまっています(図008右図)。

図008■MovieClipシンボルに[TLFテキスト]を置く

後述するとおり、Flash Player 10.2ではDisplayObject.removedFromStageイベントは呼ばれません。したがって、Flash Player 10や10.1も含めて、いずれでも同じようにイベントを扱おうとすれば少しひねりが求められます。具体的には、「TLFテキストを含むインスタンスがステージの表示リストから除かれるとき」をお読みください。

[*3] 関連する問題として、「flashx.textLayoutパッケージのクラスを使うとコンストラクタからStageにアクセスできない」があります。

[*4] [ヘルプ]の[再描画領域]は、表示しないMovieClipインスタンスは「表示リストから削除し」たうえで、「そのタイムラインを停止」することにより「CPU の使用を最小限に抑えることができ」ると説明しています。また、使わなくなったイベントリスナーは削除するべきでしょう。こうした処理が後かたづけになります。


03 Flash Player 10.2における[TLFテキスト]をもったメインタイムラインの動き
Flash Professional CS5.5つまりFlash Player 10.2でムービーの中に[TLFテキスト]を置くと、メインタイムラインの(MovieClip)インスタンスは図009のように表示リストをさまよいます。

図009■Flash CS5.5で[TLFテキスト]をもったメインタイムラインのふるまい
[1]
メインタイムライン

[2]
Stageオブジェクト
|
プリローダ
インデックス0
|
メインタイムライン
インデックス1

[3]
Stageオブジェクト
|
メインタイムライン
インデックス0

[1]まず、メインタイムラインのインスタンスがつくられるとき、いずれの表示リストにも属しません。つまり、親のないインスタンスとして生まれます。

[2]つぎに、プリローダのインスタンスとメインタイムラインがともにStageオブジェクトの子として表示リストに加わります。ただし、メインタイムラインは第二子(インデックス1)です。

[3]最後に、プリローダが消し去られると、タイムラインはStageオブジェクトの第一子(インデックス0)に繰り上がり、親ひとり子ひとりの普通の関係に落着きます。この状態に至れば、[TLFテキスト]があることをとくに気にかけなくて済みます。

[1]は前項のCS5(Flash Player 10または10.1)と同じですので、ドキュメントクラスのコンストラクタメソッドからプロパティ(DisplayObject.stageプロパティなど)を参照するときに注意が必要です。

[2]では、親インスタンス(DisplayObject.parentプロパティ)はStageオブジェクトになりますので問題ありません。しかし、Stageオブジェクトのインデックス0の子(stage.getChildAt(0))が、メインタイムラインでなくプリローダを参照します。また、前出「TLFテキストのある外部SWFを読込むとその中のオブジェクトにアクセスできない」問題は、やはり生じます。

[1]から[2]でDisplayObject.addedToStageイベントは起こるものの、CS5(Flash Player 10または10.1)とは異なり、DisplayObject.removedFromStageイベントが生じることはありません。


04 [TLFテキスト]のActionScriptライブラリをSWFに埋込む
[TLFテキスト]で使われるActionScriptライブラリをランタイム共有ライブラリとして読込むのでなく、SWFファイルに埋込んでしまうことができます。SWFファイル本体の容量は大きくなってしまう代わりに、メインタイムラインが初めからStageオブジェクトのひとりっ子として生まれますので、表示リストをさまようという前述02や03のふるまいはなくなります。

[TLFテキスト]のActionScriptライブラリをSWFファイルに埋込むには、[パブリッシュ設定]([ファイル]メニュー)の[Flash]タブにある[スクリプト]の{ActionScript設定」ボタンで[ActionScript 3.0の詳細設定]ダイアログボックスを開きます。そして、[ライブラリ]タブにある[ランタイム共有ライブラリ設定]の[デフォルトリンケージ]から[コードにマージ]を選んで、[OK]ボタンをクリックします(図010)。

図010■[ランタイム共有ライブラリ設定]の[デフォルトリンケージ]から[コードにマージ]を選ぶ

これで、Flashムービーの中に[TLFテキスト]があっても、メインタイムラインは普通どおり初めからStageオブジェクトのただひとりの子になります(前掲図001)。


作成者: 野中文雄
更新日: 2012年1月3日 注[*2]を追加
作成日: 2011年8月6日


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