大重美幸の「これ見落としてませんか? ActionScript 3.0

第2回 外部 swf ファイルのシンボルを利用する

第2回目のテーマは、「外部 swf ファイルの活用」です。みなさん、外部 swf ファイルをムービーに読み込む方法は知っているでしょう。では、外部 swf ファイルのシンボルにアクセスする方法となると、どうでしょう?

例えば、外部 swf ファイルのライブラリにある書き出し設定したムービークリップシンボルやフォントシンボルを利用するとしたら。いきなり難しい!と逃げ腰になった人も居るかもしれませんが、それだけにちょっとお得感もありますよ。人から聞かれたときにスラッと答えられれば、ポイントアップ間違いなし!

サンプルファイル : edge_oshige_02_sample_fla.zip (231KB)

「外部 swf からムービークリップやフォントを読み込める?」

いきなりですが、ライブラリにあるムービークリップシンボルからインスタンスを作る方法はわかりますか?
シンボルをリンケージ書き出しの設定にすれば、付けておいたクラス名でインスタンスを作れます。次のサンプルではクリックした位置にムービークリップインスタンスを作ります。作成するインスタンスのシンボルはUFOというクラス名でリンケージ書き出しの設定をしておきます。

クリックした位置にUFOのインスタンスを作る。


//ステージのクリックイベントにリスナーを登録する
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
//クリックした位置にUFOクラスのインスタンスを作る
function mouseDownHandler(eventObj:MouseEvent):void {
    var ufo:UFO = new UFO();
    ufo.x = eventObj.stageX;
    ufo.y = eventObj.stageY;
    addChild(ufo);
}

シンボルプロパティダイアログ
ムービークリップシンボルをUFOのクラス名でリンケージ書き出し設定をします。


クリックした位置にUFOのインスタンスが作られます。
[sample] hello_ufo.fla

では、みなさんは再生中のムービーに外部イメージファイルを読み込んで表示できることはご存じでしょう。そして同様に外部の swf ファイルをムービーに読み込めることも知っていますよね。さて、問題はここからです。読み込んだ swf のライブラリで書き出し設定しておいたシンボルからインスタンスを作るにはどうすればよいのでしょうか? 「今のUFOと同じようにすればいいんじゃないの?」と思いますが、残念ながらそれでは失敗します。

いきなりハードルが上がってしまった感があるので、まずはイメージファイルの読み込みから始めましょう。swf ファイルの読み込みとイメージファイルの読み込みの方法は同じです。イメージファイルの読み込みはLoaderクラスを使って次のように行います。読み込むファイルのURLをURLRequestクラスで指定するところがポイントです。

JPEGファイルを読み込んで表示する。


var photo:Loader = new Loader();
photo.load(new URLRequest("IMG_7841.jpg"));
photo.x=0;
photo.y=0;
//最背面に表示する
addChildAt(photo, 0);

ムービーにJPEGファイルを読み込んで表示。
ムービーにJPEGファイルを読み込んで表示します。
[sample] loadJpeg.fla

外部 swf ファイルの UFO クラスにアクセスする

swf ファイルを読み込む方法はこれと同じですが、読み込む swf に保存してあるクラスを使うので、swf が完全に読み込み終わったかどうかを判断する必要があります。load()の読み込み完了イベントはEvent.COMPLETEですが、イベントのリスナーは、Loaderのインスタンス swfLoader のcontentLoaderInfoに登録します。

swfの読み込み完了イベントのリスナーはcontentLoaderInfoに登録する。


swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);

swf の読み込みが完了したことを受けて、いよいよ UFO クラスのインスタンスを作ります。試しに次のようにそのままnew UFO()を実行するとどうなるでしょうか。結果は残念ながらコンパイルエラーです。先にvar UFO:ClassのようにUFOクラスを宣言しておけばコンパイルエラーを回避できますが、それでもUFOクラスのインスタンスを作ることはできません。

読み込んだswfのUFOクラスを作る(エラーになるスクリプト)。


// swfを読み込む
var swfLoader:Loader = new Loader();
swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
swfLoader.load(new URLRequest("stuff.swf"));
//swfの読み込み完了
function completeHandler(eventObj:Event):void {
	//読み込んだswfからUFOインスタンスを作る--エラーになる
	var ufo:MovieClip = new UFO();
	addChild(ufo);
}


[sample] loadSWFClass_Error.fla / stuff.fla(stuff.swf)

では、どうすればよいのでしょうか?

その答えが次のスクリプトです。このスクリプトを実行すると stuff.swf を読み込み、stuff.swf のライブラリで書き出し設定してある UFO クラスからインスタンスを作って表示します。ここで勘違いしてはならないのは、読み込んだ swf を表示していないところです。読み込んだ stuff.swf は表示せずに、stuff.swf に入っているムービークリップシンボルだけを利用します。

読み込んだstuff.swfにあるUFOクラスからインスタンスを作る。


// swfを読み込む
var swfLoader:Loader = new Loader();
swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
swfLoader.load(new URLRequest("stuff.swf"));
//swfの読み込み完了
function completeHandler(eventObj:Event):void {
	//読み込んだswfからUFOクラスの参照を取得する
	var domain:ApplicationDomain = swfLoader.contentLoaderInfo.applicationDomain;
	var UFO:Class = domain.getDefinition("UFO") as Class;
	//UFOクラスのインスタンスを作る
	var ufo:MovieClip = new UFO();
	ufo.x = ufo.y = 100;
	addChild(ufo);
}

UFOクラスからインスタンスを作るには、UFOクラスがどこにあるかを指定する必要があります。それを示すのがapplicationDomainプロパティです。次のスクリプトで読み込んだswfを指し示すことができます。

読み込んだswfのアプリケーションドメインを取り出す。


var domain:ApplicationDomain = swfLoader.contentLoaderInfo.applicationDomain;

そしてApplicationDomainクラスのgetDefinition()を使ってUFOクラスの参照を特定します。UFOクラスを特定できれば、ここから先は通常と同じです。new UFO()でインスタンスを作ればOKです。

UFOクラスの参照を作る。


var UFO:Class = domain.getDefinition("UFO") as Class;

[sample] loadSWFClass_OK.fla / stuff.fla (stuff.swf)

stuff.swfを読み込み、その中にあるUFOクラスのインスタンスを作って表示。
stuff.swfを読み込み、その中にあるUFOクラスのインスタンスを作って表示します。

最初のサンプルのようにクリックした位置にUFOのインスタンスを作るならば、スクリプトは次のようになります。

クリックした位置に読み込んだUFOのインスタンスを作る。


//UFOクラスの参照を入れる変数
var UFO:Class;
// swfを読み込む
var swfLoader:Loader = new Loader();
swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
swfLoader.load(new URLRequest("stuff.swf"));
//swfの読み込み完了
function completeHandler(eventObj:Event):void {
	//読み込んだswfからUFOクラスの参照を取得する
	var domain:ApplicationDomain = swfLoader.contentLoaderInfo.applicationDomain;
	UFO = domain.getDefinition("UFO") as Class;
	//ステージのクリックイベントにリスナーを登録する
	stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
}
//クリックした位置にUFOクラスのインスタンスを作る
function mouseDownHandler(eventObj:MouseEvent):void {
	var ufo:MovieClip = new UFO();
	ufo.x = eventObj.stageX;
	ufo.y = eventObj.stageY;
	addChild(ufo);
}



クリックした位置にUFOのインスタンスが作られます。UFOは読み込んだstuff.swfのシンボルです。

外部 swf ファイルのフォントを利用する

これとまったく同じ要領で読み込んだ swf ファイルのフォントシンボルを利用できます。フォントシンボルを作るには、ライブラリのメニューから [新しいフォント...] を選び、フォントシンボルにしたいフォントを選んでクラス名を付けて書き出します。次の例では Giddyup Std と Herculanum の2つのフォントシンボルを作ります。

新しいフォントシンボルを作成。
フォントシンボルを作ります。

フォントシンボルプロパティダイアログ

次にフォントシンボルを保存した swf を読み込んで、これを使ってテキストフィールドにテキストを表示してみましょう。次がそのスクリプトです。

font_stuff.swfを読み込んで、フォントシンボルを利用する。


//フォントクラスの参照を入れる変数
var Font1:Class,Font2:Class;
// swfを読み込む
var swfLoader:Loader = new Loader();
swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
swfLoader.load(new URLRequest("font_stuff.swf"));
//swfの読み込み完了
function completeHandler(eventObj:Event):void {
	//読み込んだswfからフォントの参照を取得する
	var domain:ApplicationDomain = swfLoader.contentLoaderInfo.applicationDomain;
	Font1 = domain.getDefinition("Garamond") as Class;
	Font2 = domain.getDefinition("RosewoodStd") as Class;
	//読み込んだフォントをグローバルフォントに登録する
	Font.registerFont(Font1);	
	Font.registerFont(Font2);	
	//フォントのインスタンスを作る
	var font1:Font = new Font1();
	var font2:Font = new Font2();
	//フィールドを作ってテキストを表示する
	var fld1:TextField = makeTextField(font1, 40, 0xFF0000, "Adobe Flash CS4");
	var fld2:TextField = makeTextField(font2, 60, 0x003333, "Action\nScript \n3.0");
	fld1.x = fld2.x = 30;
	fld1.y = 40;
	fld2.y = fld1.y + fld1.height + 10;
	addChild(fld1);
	addChild(fld2);
}
//埋め込みフォントを使うテキストフィールドを作る
function makeTextField(font:Font, size:int, color:uint, msg:String):TextField {
	var tf:TextFormat = new TextFormat();
	tf.font = font.fontName;
	tf.size = size;
	tf.color = color;
	var fld:TextField = new TextField();
	fld.autoSize = TextFieldAutoSize.LEFT;
	//埋め込みフォントを利用する
	fld.embedFonts = true;
	fld.defaultTextFormat = tf;
	fld.text = msg;
	return fld;
}

では、スクリプトのポイントを追って説明します。

まず、swf を読み込んだならば先の UFO クラスの場合と同じようにフォントをクラス化します。2個のフォントを使うので、それぞれFont1、Font2 としてクラスの参照を取り出します。

読み込んだswfからフォントの参照を取得する。


var domain:ApplicationDomain = swfLoader.contentLoaderInfo.applicationDomain;
Font1 = domain.getDefinition("Garamond") as Class;
Font2 = domain.getDefinition("RosewoodStd") as Class;

フォントを利用する場合はここからが一手間違います。フォントのインスタンスを作る前にFont.registerFont()を使ってフォントをグローバルフォントに登録する必要があります。

読み込んだフォントをグローバルフォントに登録する。


Font.registerFont(Font1);	
Font.registerFont(Font2);
//フォントのインスタンスを作る
var font1:Font = new Font1();
var font2:Font = new Font2();

最後にフォントのインスタンスをテキストフィールドのTextFormatオブジェクトのfontプロパティに指定しますが、ここでフォント名を指定する必要があるためにfont.fontNameのようにフォント名を取り出します。

TextFormatオブジェクトのfontプロパティにフォント名で指定する。


var tf:TextFormat = new TextFormat();
tf.font = font.fontName;

そして埋め込みフォントを利用するためにTextFieldのembedFontsプロパティをtrueにすることを忘れてはなりません。

埋め込みフォントを利用する。


fld.embedFonts = true;

以上、少し面倒な手続きですが、外部ファイルの埋め込みフォントを利用できるメリットは少なくありません。たとえば、フォントを埋め込むには開発マシンに使いたいフォントが必要ですが、swf ファイルの状態でもらっておけば開発マシンにフォントがなくても困りません。また、swf のサイズが大きくなる日本語フォントは、パブリッシュでも時間がかかります。1度パブリッシュしておけば時間も節約できます。このテクニック、ぜひメモっておいてくださいね。

font_stuff.swfから読み込んだ2つのフォントを使ってテキストを表示。
font_stuff.swfから読み込んだ2つのフォントを使ってテキストを表示します。
[sample] loadFont.fla / font_stuff.fla

日本語書体を読み込んだサンプル画面
swfがあれば手元にフォントがなくても大丈夫。
swfのサイズが大きくなる日本語フォントは、パブリッシュでも時間がかかるので開発効率もアップです。
[sample] loadFont_jp.fla / font_stuff_jp.fla

関連情報


大重美幸氏写真大重美幸
(おおしげよしゆき)

日立情報システムズ、コミュニケーションシステム研究所を経て独立。株式会社ロクナナ顧問。執筆、講師、ソフトウェア開発を行う。趣味はサーフィンとジョギング。茅ヶ崎在住。著著は約50冊。twitter @oshige、@as3note

近著:Adobe Flash CS4 詳細!ActionScript 3.0入門ノート[完全改訂版]