« TweenerやらFusekitを未だに使わないのは | メイン | Sandy 3D engine v3.0.1 »

2008年1月23日

[as2] 画像をロードしたMC 上に attachMovie

はじめてトラックバックという機能を使ってみます。緊張の一瞬です。

trick7さんがblogに「画像をロードしたMC 上に attachMovie できない」という記事を書かれてまして、これってよくいろいろと聞かれるので書いておこうと思いました。

まずテスト用に以下の図のような構成の"main.swf"と"sub.swf"というファイルを用意しました。


"sub.swf"のルートの1フレーム目には
trace(this);
とだけ書かれています。
あと、ムービークリップ「imageMC」を配置、そのなかに直接画像を配置しています。

で、"main.swf"にはリンケージ設定をした「attachMC」がライブラリに入った状態で、以下のスクリプトをルートに書いておきます。
import flash.display.BitmapData;

var loadMC:MovieClip = this.createEmptyMovieClip("loadMC",10);
var bmp1:BitmapData = new BitmapData(100,100,true,0);
var bmp2:BitmapData = new BitmapData(100,100,true,0);
var draw1:MovieClip = this.createEmptyMovieClip("draw_1",20);
var draw2:MovieClip = this.createEmptyMovieClip("draw_2",30);
loadMC._y = 120;
draw2._x = 120;

var loader:MovieClipLoader = new MovieClipLoader();
var listener = { onLoadComplete:function(){ 
    trace(loadMC.imageMC); // output : undefined
	
    loadMC.attachMovie( "attachMC", "attachMC" , 10 );
    bmp1.draw( loadMC ); // 描画されない
    draw1.attachBitmap( bmp1, 10, "auto", true );
    
	loadMC.onEnterFrame=function(){
      trace(mc.imageMC); // output : _level0.loadSWF.imageMC
      
	  bmp2.draw( loadMC ); // 描画される
      draw2.attachBitmap( bmp2, 10, "auto", true );
      delete this.onEnterFrame;
    } 
  }};
loader.addListener( listener );
loader.loadClip( "sub.swf" , loadMC );
結果は以下のようになります。

出力結果
undefined
_level0.loadMC.imageMC
_level0.loadMC
「出力結果」の3行目が"child.swf"の「trace(this);」の出力になります。

まず、AS2では読み込み元(この場合は"loadMC")が"sub.swf"のルートになります。(画像の場合も同様かと思います)
読み込みが完了した後、15行目の「loadMC.attachMovie(~」でattachしようとしているのですが、この時"loadMC"は"sub.swf"のルートになっているので、"sub.swf"のルートに attachMovie しようとしていることになります。
AS2では外部読み込みしたSWFに対してattachで配置することができません。(逆も同じです。)
なのでこの場合も配置することができないのです。


あと、合わせてよく聞かれるのが BitmapData の draw とかその辺です。というかイベントのタイミングの話になるのですが。
なので一緒にテストしてみました。
最初の図と見比べていただくと"draw1"の箇所が表示されていないのが分かります。
スクリプトでいうところの16、17行目の箇所です。
これは、"onLoadComplete"イベントが発生した時点では、読み込みは完了しているが画面上に書き出されていないことをあらわしています。
まだ書き出されていないので、13行目の参照も、結果は「undefined」になってしまいます。

そこで一連の処理が終わって、描画処理も終わった後で"draw"を実行するために"onEnterFrame"を使っています。
"onEnterFrame"は現在のフレームの処理がすべて終わった後、次のフレームに移った瞬間に実行されるので、おそらく読み込みが完了してから最短で"draw"する方法じゃないかと思います。
それが20行目から24行目になります。1回実行したらこの処理はもういらないので"delete"で削除してます。


さらについでなのでAS3でも試してみました。
sub.swf
trace(this.name);
main.swf
import flash.display.*;
import flash.net.URLLoader;
import flash.net.URLRequest;

var loadMC:Loader = new Loader();
var bmp1:BitmapData = new BitmapData(100,100,true,0);
var bmp2:BitmapData = new BitmapData(100,100,true,0);
var draw1:Bitmap = new Bitmap( bmp1, "auto", true );
var draw2:Bitmap = new Bitmap( bmp2, "auto", true );
this.addChild(loadMC);
this.addChild(draw1);
this.addChild(draw2);
loadMC.y = 120;
draw2.x = 120;

var request:URLRequest = new URLRequest('sub.swf');
var info = loadMC.contentLoaderInfo;
info.addEventListener( "complete" , listener );
function listener( e ){ 
  trace(loadMC.getChildByName("imageMC")); // null
  trace(loadMC.getChildAt(0).getChildByName("imageMC").name); // imageMC
  
  //mc.addChild( new attachMC() );//Error: Error #2069: Loader クラスは、このメソッドを実装しません。
  loadMC.getChildAt(0).addChild( new attachMC() );
  bmp1.draw( loadMC );
  
  loadMC.addEventListener( "enterFrame" , function(e){
    trace(loadMC.getChildByName("imageMC")); // null
    trace(loadMC.getChildAt(0).getChildByName("imageMC").name); // imageMC
    
    bmp2.draw( loadMC );
    loadMC.removeEventListener( "enterFrame" , arguments.callee );
  } );
}; 
loadMC.load( request );

出力結果
instance4
null
imageMC
null
imageMC
AS3だと外部ファイルにも"new"で配置できるんですね。
AS2と違っているのは"loadMC"が"sub.swf"のルートになるんじゃなくて、"loadMC"の中に"sub.swf"が入るようになったんですね。
あと、この結果からイベントのタイミングが描画されたあとに発生してるのもわかります。

なんか異様に長くなってしもた。
追記:
サンプルのflaファイルをアップしときました
attach_sample.zip

投稿者 michi : 2008年1月23日 22:23

« TweenerやらFusekitを未だに使わないのは | メイン | Sandy 3D engine v3.0.1 »

トラックバック

このエントリーのトラックバックURL:
http://system.seyself.com/mt-tb.cgi/226

コメント

トラックバック効いて無くない?

投稿者 カトペ : 2008年1月25日 14:49

>カトっぺさん
効いてないのか、スパム扱いで承認されてないか、かなあ。
トラックバックって実際何が起こるのかよく分かってないし。(そんな状態で使ってみるのもどうかと思うけども。)

投稿者 michi : 2008年1月25日 20:10

はじめまして。trick7のteraと申します。
リンクしていただいてありがとうございました。
記事あとでじっくり拝読させていただきます!

トラックバックは僕の記事に対してされたのでしょうか?
僕もトラックバックがよくわかってなくて、トラバを受け付ける設定にしているかどうかも怪しい(設定箇所が何カ所かあるので。。)のですみません。
ちなみに今回はGoogleで辿り着きました。
今後ともよろしくお願いいたします。
とりいそぎ。

投稿者 tera : 2008年2月16日 11:46

(重複投稿だったらけしてください。すいません。)
はじめまして。trick7のteraと申します。
リンクしていただいてありがとうございました。
記事あとでじっくり拝読させていただきます!

トラックバックは僕の記事に対してされたのでしょうか?
僕もトラックバックがよくわかってなくて、トラバを受け付ける設定にしているかどうかも怪しい(設定箇所が何カ所かあるので。。)のですみません。
ちなみに今回はGoogleで辿り着きました。
今後ともよろしくお願いいたします。
とりいそぎ。

投稿者 tera : 2008年2月16日 11:48

onLoadCompleteはロード直後
onLoadInitがロード後1フレーム目に入ったとき

だったとおもいます。
ですのでonLoadCompleteの時点では描画対象が取得できないのではないでしょうか。

同様に、loadMovieすると対象MCの動的な変数がクリアされるのでonLoadCompleteでtargetになにかしてもonLoadInitで初期化されてしまうことになります。

というか、なぜ初期化されるのかがまさにこのエントリーで書かれている部分ですね。

投稿者 どうけ : 2008年2月17日 22:12

teraさん >
どうもはじめまして。
blogの方では興味深い内容の記事が多く、
いつも拝見させていただいております。
やはりトラックバックは人様のblogに関わってきそうですし、よく分からないので、使い方がはっきり理解できるまで控えようと思います。
どうもお騒がせしました。

どうけさん >
onLoadInitを僕はonLoadStartの前に実行されるものと勘違いしてました。お恥ずかしい。
で、少し試してみました。
ソースを掲載するために新しく記事を投稿しておきます。
http://blog.seyself.com/2008/02/post_200802181335.html

助言ありがとうございます。

投稿者 michi : 2008年2月18日 13:37

コメントしてください




保存しますか?