feb19.jp blog - life is creative!

loader.unload と addChild/removeChild に関する、Flash Player 9 と 10 の微妙な差異

ブックマークに追加する tags:     

loader.unload と addChild/removeChild に関する、Flash Player 9 と 10 の微妙な差異

Flash CS4 Professional で開発を行っていると、ムービーをプレビューで確認するときは基本的に Flash Player 10 になってしまうので、Flash Player 9 用コンテンツを作っているとややその動作の差異に頭を悩ませる事はしばしばあります。

なんだかんだで Flash サイトはまだ Flash Player 9 対象が基本。Flash CS5 が出たら Flash Player 10 または 11 が基本になるんだろうか。Flash Player 11 では Dynamic Sound Generate の機能が強化されるといいなぁ。今のバッファサイズじゃレイテンシとかがちょっと悩ましい。簡単サウンド API が提供されるともっといいな。


Flash Player 9 の場合、外部からロードするコンテンツを addChild(loader) ではなく、 addChild(loader.content) するようにしておくと、removeChild(loader.content) して unload() するときにエラーが出てしまいます。

これが Flash Player 10 だったりすると、エラーは出ず正常に removeChild() と unload() が行われます。

ためしたサンプルコード。各ボタンを押した瞬間、red.swf、blue.swf、green.swf をロードしています。

red_btn.addEventListener(MouseEvent.CLICK, clickHandler);
blue_btn.addEventListener(MouseEvent.CLICK, clickHandler);
green_btn.addEventListener(MouseEvent.CLICK, clickHandler);
 
//ロードされるコンテンツのコンテナー
var container:Sprite = new Sprite();
container.y = 100;
addChild(container);
 
//ローダー。このローダーを使い回す。
var loader:Loader;
 
//現在ロードしてるコンテンツ名を格納しておく。
var current:String = "";
 
function clickHandler(event:MouseEvent):void
{
	var target:MovieClip = MovieClip(event.currentTarget);
	var swfName:String = target.name.substr(0, target.name.lastIndexOf("_"));
	loadContent(swfName);
}
 
function loadContent(swfName:String):void
{
	if (current == swfName)
		return;
	
	if(loader && loader.content)
	{
		container.removeChild(loader.content);
		loader.unload();
		loader = null;
	}
	
	current = swfName;
	
	loader = new Loader();
	loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
	loader.load(new URLRequest(swfName + ".swf"));
}
 
function loadCompleteHandler(event:Event):void
{
	var loader:Loader = LoaderInfo(event.currentTarget).loader;
	loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadCompleteHandler);
	container.addChild(loader.content);
}

Loader でロードした中身(content)を親の DisplayObjectContainer に addChild し、消すときは removeChild で Loader の中身を親から取り外したあと、Loader をクリア(unload)。この瞬間に Flash Player 9 だとエラーが出ます。

ArgumentError: Error #2025: 指定した DisplayObject は呼び出し元の子でなければなりません。
	at flash.display::Loader/unload()
	at main_fla::MainTimeline/loadContent()[main_fla.MainTimeline::frame1:31]
	at main_fla::MainTimeline/clickHandler()[main_fla.MainTimeline::frame1:20]

Flash Player 10 で同じくダメなのであれば「そういうものなのね」で自己解決できるのですが、問題なく出来てしまいますし、心持ちこちらの方が美しい気がするので悩ましい所。(MVC 的に Loader という Controller と、content という View な感じ)

これを解決するには loader.content を addChild するのではなく、 loader を addChild するかたちにして、removeChild のときも同様にすれば解決できます。

上のコードの問題を解消したサンプルコード。loader.content ではなく、loader を addChild しています。

red_btn.addEventListener(MouseEvent.CLICK, clickHandler);
blue_btn.addEventListener(MouseEvent.CLICK, clickHandler);
green_btn.addEventListener(MouseEvent.CLICK, clickHandler);
 
//ロードされるコンテンツのコンテナー
var container:Sprite = new Sprite();
container.y = 100;
addChild(container);
 
//ローダー。このローダーを使い回す。
var loader:Loader;
 
//現在ロードしてるコンテンツ名を格納しておく。
var current:String = "";
 
function clickHandler(event:MouseEvent):void
{
	var target:MovieClip = MovieClip(event.currentTarget);
	var swfName:String = target.name.substr(0, target.name.lastIndexOf("_"));
	loadContent(swfName);
}
 
function loadContent(swfName:String):void
{
	if (current == swfName)
		return;
	
	if(loader && loader.content)
	{
		container.removeChild(loader);
		loader.unload();
		loader = null;
	}
	
	current = swfName;
	
	loader = new Loader();
	loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
	loader.load(new URLRequest(swfName + ".swf"));
}
 
function loadCompleteHandler(event:Event):void
{
	var loader:Loader = LoaderInfo(event.currentTarget).loader;
	loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadCompleteHandler);
	container.addChild(loader);
}

addChild(loader) ってなんかすごい気持ち悪い気がするのですが、そもそも loader は DisplayObject なんだ思うと、ぐっとこらえられる気もします。

---

そういえば先月の Web Designing の「Flash の学校」で、Flash Player 10 の機能である「Dynamic Sound Generate」を使ったプライベートワークの「A Flash Polyphonic Synthesizer」がこっそり載っていました

プライベートワークが本に載ったのは初めてです。多分。ちょっと嬉しかったです。よろしければ触ってみた事がない方は触ってみてください。デザインもインタラクションも、あまりにも適当なので、今度はそのあたり頑張ります。

2009年08月25日10:11

Webデザインブログ

「loader.unload と addChild/removeChild に関する、Flash Player 9 と 10 の微妙な差異」の関連エントリー

 iTunes Store(Japan)

コメントを投稿

トラックバック

このエントリーのトラックバックURL:
http://feb19.jp/mt/mt-tb.cgi/176

この一覧は、次のエントリーを参照しています: loader.unload と addChild/removeChild に関する、Flash Player 9 と 10 の微妙な差異:

» 【薬物】沢尻エリカ 重大違反で解雇【逮捕】 送信元 【薬物】沢尻エリカ 重大違反で解雇【逮捕】
【薬物】沢尻エリカ 重大違反で解雇【逮捕】 女優沢尻エリカ(23)が25日までに、所属事務所「スターダストプロモーション」から解雇通... [詳しくはこちら]

Navigation

古:ありがとう Tweener/最終版 Tweener 1.33.74 小技
新:Flash Develop に見切りを付けて Flex/Flash Builder Eclipse plugin を入れるプレイ
トップページ

Recently Entries
Mac でファイルの関連付けを変える(Mac で AIR アプリがアップデート出来ないを解決する方法)
ファイルを右クリックして「情報を見る」を選び、表示されたウィンドウの...
Mac OS X 10.6 Snow Leopard から入ってるフォント「Menlo」がコーディング作業にいい感じ
Xcode でコード書いているとき、Eclipse でコード書くより...
AIR で JSON 形式ファイルの入出力
AIR 祭り開催中。今回はファイル入出力。AS3 で扱っている Ob...
Adobe CS5 ティザーサイトオープン
カウントダウンが始まっています。いよいよ CS5 ですね。globa...
AIR でファイルがドラッグアンドドロップされたことを NativeDragEvent で検知する
最近また AIR が楽しい気がして触っているのですが、 Google...
iPhone アプリ "iBeat - BPM Counter" を発売しました & iPhone インタラクションデザインについて
BPM 計測アプリです。既に似たようなアプリはいくつか発売されている...
AS3 の演算子 ||= について
AS3 だけでつかえるものではないのですが、AS3 での動作を確認し...
iPhone SDK 「カテゴリ」について+NSString の空白文字を除去する
Objective-C では、高位のフレームワークで、低位のフレーム...
Flash CS4 で Flex SDK (mx パッケージ、クラス) を使う
Flex 用のライブラリとかを見ると mx パッケージとか使われてい...
Flash CS5 を予習 ~Text Layout Framework (TLF) 編~
Text Layout Framework (TLF) を使って、F...