feb19.jp

Nobuhiro Takahashi
Designer / Engineer

AS3で外部のSWFをロードする処理

AS3で外部のSWFをロードする処理

AS3ではloadMovieやらMovieClipLoaderやらが無くなったので、Loaderを使いましょうというだけの超初歩的サンプルとコードのメモ。

サンプル

LoaderTestMain.swfのbtnというムービークリップをクリックするとLoaderTestSub.swfが現れるという仕組み。

new Loader()でLoaderインスタンスを作って、ロードするURLをnew URLRequestで作る。で、Loader.load(url)。これでロード処理が走る。処理が走ったところで表示はされないので、ロード完了時にLoaderインスタンスをaddChild()する必要がある。つまりイベントの監視をする必要がある。

Loaderインスタンスの中にcontentLoaderInfoというオブジェクトプロパティがあるのでこれに.addEventListenerする。たとえばEvent.COMPLETEやProgressEvent.PROGRESSなど。

LoaderInfo クラス

loader.contentLoaderInfo イベント一覧

complete:Event — ファイルのロードが完了したときに、関連する LoaderInfo オブジェクトによって送出されます。complete イベントは、常に init イベントの後に送出されます。
httpStatus:HTTPStatusEvent — ネットワーク要求が HTTP を介して行われ、Flash Player が HTTP 状況コードを検出できる場合に、関連する LoaderInfo オブジェクトによって送出されます。
init:Event — ロードされた SWF ファイルのプロパティおよびメソッドにアクセスできる場合に、関連する LoaderInfo オブジェクトによって送出されます。init イベントは、常に complete イベントの前に送出されます。
ioError:IOErrorEvent — 入出力エラーが発生してロード処理が失敗したときに、関連する LoaderInfo オブジェクトによって送出されます。
open:Event — ロード処理が開始したときに、関連する LoaderInfo オブジェクトによって送出されます。
progress:ProgressEvent — ロード処理を実行中にデータを受信したときに、関連する LoaderInfo オブジェクトによって送出されます。
unload:Event — ロードされたオブジェクトが削除されるときに、関連する LoaderInfo オブジェクトによって送出されます。

COMPLETEイベントのコールバック関数でLoaderインスタンスを表示リストにaddChildする。ダウンロードの進捗状況はProgressEventで計測して「ナウローディング」のソースにする。

ここまでがロードする処理。

逆にアンロードする時はまずLoaderインスタンスを表示リストから外して、Loader.unload()。

以下サンプルのLoaderTestMain.swf側のソース。

サンプルをダウンロード

package {
	import flash.display.*;
	import flash.net.*;
	import flash.events.*;
	public class Main {
		private var basemc:MovieClip;
		private var isLoaded:Boolean;
		private var loaderObj:Loader;
		public function Main(mc){
			basemc = mc;
			isLoaded = false;
						
			basemc.stage.align = "TL";
			basemc.stage.scaleMode = "noScale";
			basemc.stage.showDefaultContextMenu = false;
			basemc.stage.addEventListener(Event.RESIZE, onResizeHandler);
			onResizeHandler(null);
			
			setBtn();
		}
		private function onResizeHandler(e:Event):void{
			basemc.btn.x = basemc.stage.stageWidth - 100;
		}
		private function setBtn():void{
			basemc.btn.buttonMode = true;
			basemc.btn.addEventListener(MouseEvent.CLICK, onReleaseHandler);
		}
		private function onReleaseHandler(e:MouseEvent):void{
			if(isLoaded){
				unloadSWF();
				isLoaded = false;
			} else {
				loadSWF();
				isLoaded = true;
			}
		}
		private function loadSWF():void{
			loaderObj = new Loader();
			var url = new URLRequest("LoaderTestSub.swf");
			loaderObj.load(url)
			loaderObj.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadedSWF);
			loaderObj.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onLoadingSWF);
		}
		private function onLoadedSWF(e:Event):void{
			trace("complete" + loaderObj);
			basemc.addChild(loaderObj);
		}
		private function onLoadingSWF(e:ProgressEvent):void{
            trace("progressHandler: bytesLoaded=" + e.bytesLoaded + " bytesTotal=" + e.bytesTotal);
		}
		private function unloadSWF():void{
			basemc.removeChild(loaderObj);
			loaderObj.unload();
		}
	}
}

ただし、子側つまりアンロードされる側のSWFで鳴っている音や映像など、ストリームはそのまま残り続けてしまい、unloadしても子の音は鳴り続けてしまうというバグが起きてしまう。そのため、unloadのイベントを受け取る子にイベントリスナーを追加しておくと、親が Loader.unload()をしたとき、unloadイベントが子に対して送出されるので、そのコールバック関数でNetConnectionやNetStreamなどを.close()すればいい。ちなみにこのunloadイベントはこのエントリーで掲載しているサンプルには載せていません(必要ないから)。

Loader.unload()

load() メソッドを使用してロードされた、 Loader オブジェクトの子を削除します。関連した LoaderInfo オブジェクトの property は null にリセットされます。他のオブジェクトが参照している可能性があるため、子は必ずしも破棄されるとは限りません。ただし、Loader オブジェクトの子ではなくなります。
子 SWF ファイルをアンロードする前に、LocalConnection、NetConnection、NetStream、Sound オブジェクトなど、子 SWF ファイルのオブジェクト内のストリームをすべて明示的に閉じておくことをお勧めします。そうしなかった場合は、子 SWF ファイルがアンロードされた後も、子 SWF ファイルのオーディオの再生が続く場合があります。子 SWF ファイルのストリームを閉じるには、unload イベントを受け取る子にイベントリスナーを追加します。親が Loader.unload() を呼び出すと、unload イベントが子に対して送出されます。次のコードは、このような処理を行う例を示します。

function closeAllStreams(evt:Event) { myNetStream.close(); mySound.close(); myNetConnection.close(); myLocalConnection.close(); } myMovieClip.loaderInfo.addEventListener(Event.UNLOAD, closeAllStreams);

あと大量に画像使うときとかはメモリリークとかも気にしないといけなくて、ガベージコレクションとかその辺も理解しないといけない。うひょーめんどくせー。

spf designな方がそれの解決法(強制的にガベージコレクションを行う方法)を解説してます。 なんか裏技的ですね。

Tweet Share Bookmark

Navigation

prev: 旅行@山梨
next: AS3でEventDispatcherを使う

Recently Entries