ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Flashコミュの【質問:AS3】 MovieClipLoader の onLoadComplete は何処へ?

  • mixiチェック
  • このエントリーをはてなブックマークに追加
【質問:AS3】 MovieClipLoader の onLoadComplete は何処へ?
  (onClipEvent(load) や onClipEvent(initialize) は何処へ?)

ActionScript 3.0 (Flash CS4) での質問です。
以下はかなり長文ですが質問内容は単純です。

親SWF(仮称「oya.swf」)に,子SWF(「ko.swf」)をロードするとします。
このとき
子SWF内の フレーム1 のスクリプトが実行される直前に
親SWFから変数を送りこむにはどうすればいいのでしょうか?

↑質問はこれだけです。



◎ActionScript 2.0 では次のようにするとできます。

○ 「oya.swf」 に書くスクリプト例↓

------------------
//空のMC「ko_ld」を作成
var ko_ld:MovieClip = this.createEmptyMovieClip("mc", 0);

//MovieClipLoaderインスタンス「ko_mcl」を作成
var ko_mcl:MovieClipLoader = new MovieClipLoader();

//リスナーにするオブジェクト「ko_lsn」を作成
var ko_lsn:Object = new Object();

//★onLoadCompleteのタイミングで実行
ko_lsn.onLoadComplete = function():Void {
//「ko_ld(ko.swf)」内の変数 num の値として 123 を代入
ko_ld.num = 123;
};

//「ko_lsn」を「ko_mcl」のリスナーとして登録
ko_mcl.addListener(ko_lsn);

//「ko.swf」をロード
ko_mcl.loadClip("ko.swf", ko_ld);
------------------

○ 「ko.swf」 のフレーム1 に書くスクリプト例↓

------------------
trace(num); //→出力「123」
------------------

↑これを ActionScript 3.0 でする場合です。



◎ActionScript 3.0 で一応次のような感じにしてみました。

○ 「oya.swf」 に書いたスクリプト例↓

------------------
//Loaderiインスタンス「ko_ld」を作成
var ko_ld:Loader = new Loader();

//★COMPLETEのタイミングでsetVarsを実行
ko_ld.contentLoaderInfo.addEventListener(Event.COMPLETE,setVars);

//setVarsの定義
function setVars(evt:Event) {
MovieClip(ko_ld.content).num = 123;
}

//「ko_swf」をロード & 配置
var ko_file:URLRequest = new URLRequest("ko.swf");
ko_ld.load(ko_file);
addChild(ko_ld);
------------------

○ 「ko.swf」 のフレーム1 に書いたスクリプト例↓

------------------
var num;
trace(num); //→出力「undefined」
------------------

※ちなみに
 「ko.swf」 のフレーム1 に書いたスクリプトを
 フレーム2 に移動させると
 無事に 「123」 が出力されます。


上記スクリプトで

//★COMPLETEのタイミングでsetVarsを実行
ko_ld.contentLoaderInfo.addEventListener(Event.COMPLETE,setVars);

と書いた部分を
次のように変えても結果は同じでした。

//★HTTP_STATUSのタイミングでsetVarsを実行
ko_ld.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS,setVars);

また次のように変えても結果は同じでした。

//★INITのタイミングでsetVarsを実行
ko_ld.contentLoaderInfo.addEventListener(Event.INIT,setVars);

とにかく
COMPLETE でも HTTP_STATUS でも INIT でも
結果は「undefined」です。
またどの場合でも
「ko.swf」 のフレーム1 に書いたスクリプトをフレーム2 に移動させると
無事に 「123」 が出力されます。


trace などを使って実験調査してみると
実行順番は次のようになることがわかりました。

  ▼子SWFのフレーム1▼
    ↓
  親SWFの Event.INIT
    ↓
  親SWFの HTTPStatusEvent.HTTP_STATU
    ↓
  親SWFの Event.COMPLETE
    ↓
  (子SWFのフレーム1に書いた Event.ENTER_FRAME)
    ↓
  ▲子SWFのフレーム2▲

3つとも MovieClipLoader の onLoadInit とほぼ同じようです。
(なぜか MovieClipLoader の onLoadInit の実行は
onLoadComplete より遅いです。←AS3 とは逆?)

ActionScript 2.0 以下の場合は次のような順番です。

  親SWFの 子SWFロード時 onClipEvent(initialize)
    ↓
  親SWFの MovieClipLoader の onLoadComplete
    ↓
  親SWFの 子SWFロード時 onClipEvent(load)
    ↓
  ▼子SWFのフレーム1▼
    ↓
  親SWFの MovieClipLoader の onLoadInit
    ↓
  (子SWFのフレーム1に書いた this.onEnterFrame)
    ↓
  ▲子SWFのフレーム2▲

ActionScript 2.0 以下では
子SWFのフレーム1 よりも早く実行できるスクリプトはたくさん見つかります。。。

コメント(4)

ActionScript 2.0でもそうですけど、できるだけタイムラインのスクリプト実行順序に依存しないつくりにする方がよいと思います。

// oya.swf
// function setVars(evt:Event) {;
function setVars(evt:Event):void {
 // MovieClip(ko_ld.content).num = 123;
 MovieClip(ko_ld.content).init(123);
}

// ko.swf
var num:int;
stop();
function init(i:int):void {
 num = i;
 trace(num);
}
Fumio さん
回答ありがとうございます。

なるほど。。。
子SWF の フレーム1 に 引数を trace する関数を用意しておいて
親SWF から その 子SWF の関数を引数付きで実行させるということですね。

具体的に全文を書けば次のようになります。

---oya.swf----------------------
//Loaderiインスタンス「ko_ld」を作成
var ko_ld:Loader = new Loader();

//★COMPLETEのタイミングでsetVarsを実行
ko_ld.contentLoaderInfo.addEventListener(Event.COMPLETE,setVars);

//setVarsの定義
function setVars(evt:Event):void {
MovieClip(ko_ld.content).init(123);
}

//「ko_swf」をロード & 配置
var ko_file:URLRequest = new URLRequest("ko.swf");
ko_ld.load(ko_file);
addChild(ko_ld);
-------------------------------


---ko.swf フレーム1--------
var num:int;
stop();
function init(i:int):void {
num = i;
trace(num);
}
-----------------------

書かれていらっしゃる通りでうまく動作しました。
ありがとうございました。



> できるだけタイムラインのスクリプト実行順序に
> 依存しないつくりにする

できればそうしたいのですが,
なかなかそうは行かないわけでして。。。

ご提示していただいた方法でも
「スクリプト実行順序を知っているからこそ書けること」
であって
「スクリプト実行順序を知らなくても(依存しなくても)書けること」ではありませんよね。

「Event.COMPLETE は ロードした子SWF のフレーム1よりも後,フレーム2よりも前に実行される。」
したがって
「 function init は 子SWF のフレーム1 で定義する必要がある。」
  ↑↑↑
すごくややこしい条件です。。。



ですからそもそも
「親SWFから子SWFに変数を送り込む」
などという考え方をせずに
「変数は親SWFにあらかじめ用意しておいた上で子SWFをロードし
子SWFから親SWFの変数などを取得するようにする」
という路線で考えた方が良いということですね。

参考になりました。
>> 2: ささきちさん
>「スクリプト実行順序を知らなくても(依存しなくても)書けること」ではありませんよね。
_____
書き方が悪かったですね。書いた後、そうは思ったのですけど(笑)。

正確には、(1)「ロードされたSWFファイルのプロパティおよびメソッドがアクセス可能」で(2)そのSWFの第1フレームアクションはまだ実行される前というタイミングが保証されないということです。(1)はLoaderInfo.initおよびその後に発生するLoaderInfo.completeイベントで仕様として定められています。実際LoaderInfoクラスのイベントをざっと試したところでは、(1)より後で(2)より前に発生するイベントは見当たりませんでした。

> 「変数は親SWFにあらかじめ用意しておいた上で子SWFをロードし
子SWFから親SWFの変数などを取得するようにする」
という路線で考えた方が良いということですね。
_____
そういうことだと思います。
>>3 Fumio さん

回答ありがとうございます。
また返事が遅れましてすみません。


> (2)より前に発生するイベントは見当たりませんでした。

そうでしたか。残念ですがそう理解します。
ActionScript が FlashVars(HTMLからの命令(他人からの命令)) に負けるところも悔しい気がしますが。。。

もっとも
URLURLRequest を ○○.swf?△△=□□ にすれば
FlashVarsと同じになって良いのかもしれませんが,
これは ActionScript での方法はありませんしね。。。

---oya.swf----------------------------
//Loaderiインスタンス「ko_ld」を作成
var ko_ld:Loader = new Loader();

//「ko_swf」をロード & 配置
var ko_file:URLRequest = new URLRequest("ko.swf?num=123");
ko_ld.load(ko_file);
addChild(ko_ld);
------------------------------------

---ko.swf----------------------------
var my_txt:TextField = new TextField();

my_txt.text = loaderInfo.parameters.num;

addChild(my_txt);
------------------------------------




>> という路線で考えた方が良いということですね。
> _____
> そういうことだと思います。

はい。
なるべく意図的に決めた(仕組んだ)順序で
確実に動作させるようにこころがけるようにします。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

Flash 更新情報

Flashのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング