外部swfからクラスを呼び出す

画像が固定(更新なし)のスライドショー的なものを作っていて、外部swfにひとまとめにして、そこから画像を取り出そうと考えてみた。

画像はphoto.swfに入れて、そのライブラリのプロパティでリンケージを設定して「photo0」のようにクラス名をつけておく。それで書き出すだけ。
で、取り出しはSWFをロードするクラスに書きます。
package {
import flash.events.EventDispatcher;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.net.URLRequest;
import flash.events.Event;
import flash.system.LoaderContext;
import flash.system.ApplicationDomain;
import flash.events.ProgressEvent;
public class SwfLoader extends Loader {
var flg_play:Boolean;
var func_complete:Function;
private var cont:LoaderContext;
//コンストラクタ
function SwfLoader(url:String,isPlay:Boolean,func_comp:Function = null) {
flg_play = isPlay;
func_complete = func_comp;
//各種イベント定義
this.contentLoaderInfo.addEventListener(Event.INIT,onInit_swf);
this.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoaded_swf);
this.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onLoadProgress_swf);
//for URL
var urlReq:URLRequest = new URLRequest(url);
cont = new LoaderContext();
cont.applicationDomain = ApplicationDomain.currentDomain;
this.load( urlReq, cont);
}
//—–Event.INIT
function onInit_swf(evt:Event):void {
//ロード中は再生しないよう停止
var info:LoaderInfo = LoaderInfo(evt.target);
var mc:MovieClip = info.content as MovieClip;
mc.stop();
}
//swf:ロード継続
private function onLoadProgress_swf(e:ProgressEvent):void {
//継続イベント:送信(ProgressEvent.PROGRESSを引き継ぐ)
dispatchEvent(e);
}
//—–Event.COMPLETE
function onLoaded_swf(evt:Event):void {
try {
//指定関数の呼び出し(LoaderInfo.contentを渡す)
var info:LoaderInfo = LoaderInfo(evt.target);
var mc:MovieClip = info.content as MovieClip;
//再生の有無
if (flg_play) {
mc.play();
} else {
mc.stop();
}
if (func_complete != null) {
func_complete(mc);
}
} catch (err:TypeError) {
trace(err.message);
}
}
public function getImage():Loader {
return this;
}
public function checkClass(ClassName:String):Class {
var cl:Class;
//アプリケーションドメインに指定したクラスがあるか
if (cont.applicationDomain.hasDefinition(ClassName)) {
//取得したクラスをClass型変数に代入
cl = cont.applicationDomain.getDefinition(ClassName) as Class;
trace(“外部SWFファイルから”+ClassName+”クラスをインポートしました”);
} else {
trace(“外部SWFファイルには”+ClassName+”クラスは存在しません”);
}
return cl;
}
}
}

本体側では、こんな感じにswfをロードして・・・

import SwfLoader;
var swf_content:SwfLoader;
//画像用swf:ロード
function loadContent_img():void {
var url:String = “photo.swf”;
var flg_play:Boolean = false;
swf_content = new SwfLoader(url,flg_play);
swf_content.addEventListener(ProgressEvent.PROGRESS, checkLoad_font);
this.addChildAt(swf_content,1);
}
SwfLoaderのcheckClass()という関数を使って、外部swfからBitmapDataを取得します。
//ビットマップ取得
function getBitmap_img(no:int):Bitmap {
var name_bmp:String = “photo” + String(no);
var imgClass:Class = swf_content.checkClass(name_bmp);
if (imgClass != null) {
var img:BitmapData = new imgClass(stage.stageWidth,stage.stageHeight);
var bmp:Bitmap = new Bitmap(img);
}
return bmp;
}

納品先での画像差し替えが不要で、定期的に一括更新かけるような場合は便利かも。作例はこちら

下記のサイトを参考にさせていただきました。
 

フレームラベルに数値を使ってはいけない

たまたま仕事でもらったflaファイルに”00″〜”09″までのフレームラベルがついていたので、何気なく単純にフレーム制御しようとしたらフレーム番号に移動してしまった。例えば・・・
this.gotoAndStop(“07”)
と書くと、フレーム番号7に移動するといった具合。
でテストしてみました。1フレーム目に・・・
this.stop();
goFrame(“07”)
function goFrame(st:String):void {
this.gotoAndStop(st);
}
と書き、任意(フレーム番号7以外)のフレームラベルを”07″にして、1〜100フレームのライムラインに
this.stop();
trace(“—“,this.currentFrame);
と書いて実行。
結果は、やはりフレーム番号に移動。どうも数字のみのフレームラベルは数値として見なされてしまう模様。”7″でも”007″でも結果は一緒でした。AS2でも確認しましたが、結果は同じです。
ちなみに”00″の場合はフレーム移動せず、エラーにもなりませんでした(AS3.0ではフレームラベルが存在しないとエラーが出る)。
普段は必ず「英字」又は「英字+数字」のフレームラベルをつけるクセがついてるので、こんなことにはならないのですが、一応メモとして残しておきます。

Tweenerでフィルタ効果を使う

つい最近知りました。Tweenerでフィルタ効果が使えるんですねえ(笑)。
フィルタ用のライブラリ(caurina.transitions.properties.FilterShortcuts)をimportして初期化してやるだけ。もっと早く知ってれば、自前でちくちく書かなくてもよかったのに。よく見ればTweenerのヘルプに載ってるし…。
this.stop();
import caurina.transitions.Tweener;
import caurina.transitions.properties.FilterShortcuts;
FilterShortcuts.init();
//title_mc:ブレで登場
Tweener.addTween( title_mc, 
{_Blur_blurX:100,_Blur_blurY:0, 
_Blur_quality:2,time:0, transition:”linear”});
Tweener.addTween( title_mc, 
{_Blur_blurX:0,_Blur_blurY:0, 
_Blur_quality:2,time:1.5, transition:”easeOutCubic”,onComplete:goNext});
//次のフレームへ
function goNext():void {

this.gotoAndPlay(this.currentFrame+1);

}

ちなみにカラーをいじる場合は、ColorShortcutsを同じように使います。
this.stop();
import caurina.transitions.Tweener;
import caurina.transitions.properties.ColorShortcuts;
ColorShortcuts.init();
Tweener.addTween(BG_mc,
 {_tintBrightness:0,time:2,transition:”easeOutQuad”,onComplete:goNext});

下記のサイトを参考にさせていただきました。

半角相当での文字数を調べる

今更だけど「全角●●文字まで」って入力制限があって、単に文字数だと全角も半角も1文字になってしまうので、関数を書いてみました。
文字をエンコードしてみて1文字なら半角、2文字以上なら全角3文字を越えたら全角・・・っていう判断です。String.length()は改行コードも1文字にカウントするので、改行コードは統一した上で除外(半角カナが3文字の場合があるので修正)。
これが最善かはわかりませんが…。みんなどうやってるんだろう?
//半角相当での文字数を調べる(改行コードは除外)
function xGetCharLength(str:String):int {
//改行コード統一
var val:String = str.replace(“\r\n”,”\r”).replace(“\n”,”\r”);
var array:Array = new Array();
var count_char:int = 0;
for (var i:int = 0; i<val.length; i++) {
//改行コードは除外
if (val.charCodeAt(i) != 13) {
                        if (escapeMultiByte(val.charAt(i)).length > 1) {
if (escapeMultiByte(val.charAt(i)).length > 3) {
count_char += 2;
} else {
count_char+=1;
}
}
}
return count_char;
}
[2010.12.16 訂正]

野中さんのご指摘を受けて、訂正しました。野中さんが書かれた文字数チェックはこちら。

文字列の有無によるテキストフォーマット設定方法の違い

ずっと前に個人的にメモってたんだけど、今日「あれ?」となったので改めてココに書いておきます。

———————————————

TextFieldのフォーマットを設定するときに、getTextFormat,setTextFormatを使う。

でもテキストがないTextFieldだとフォーマットが適用されない。その場合は、defaultTextFormatを使う。

要は・・・

・setTextFormat>テキストがある場合

・defaultTextFormat>テキストがない場合

ということらしい。

//テキストフォーマット:設定(テキストあり)
function xSetTextFormat(txt:TextField):void {
var tf:TextFormat = txt.getTextFormat();
tf.color = “0xff0000”
//空のテキストに対しては、
//defaultTextFormatを使うこと。
txt.defaultTextFormat = tf;
}
//テキストフォーマット:設定(テキストなし)
function xSetTextFormat2(txt:TextField):void {
var tf:TextFormat = txt.getTextFormat();
tf.color = “0xff0000”
//入力済みテキストに対しては、
//setTextFormatを使うこと。
txt.setTextFormat(tf);
}