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
AS3 で Flash コンテンツに YouTube Player を埋め込む
AS3 用の Google 公式 YouTube 埋め込みプレイヤー...
AS3 で SWFAddress 2.4 を使う ( Flash でブラウザの戻るボタン、パーマリンクに対応する )
Flash サイトのページ内で移動すると、ブラウザの戻るボタンが聞か...
SWFAddress 2.4 リリース
SWFAddress が 2.4 にバージョンアップしていました。主...
AS3 の FileReference.upload() の使い方と注意すべき点
ユーザー参加コンテンツで「ユーザーが自由にファイルをアップロードした...
Flash CS5 Professional で iPhone アプリを作れるように
アメリカで開催されている Adobe MAX 2009 にて CS5...
Flash Develop に見切りを付けて Flex/Flash Builder Eclipse plugin を入れるプレイ
もうここ最近 Windows 環境で ActionScript を書...
loader.unload と addChild/removeChild に関する、Flash Player 9 と 10 の微妙な差異
Flash CS4 Professional で開発を行っていると、...
ありがとう Tweener/最終版 Tweener 1.33.74 小技
Flash のトゥイーン系ライブラリのスタンダードとも言える Twe...
Flash CS4 の新モーショントゥイーンは「ピクッ」ってならない
「回転したムービークリップ」(特に写真とかを含むムービークリップだと...
iPhone アプリ開発に効く8冊の本/iPhone SDKオススメ書籍
Mac なソフトウェアを作るのに興味があったのと、iPhone SD...