Flex3でLoaderで読み込んだSWFをMovieClipに変換した際にnullになってしまう
外部SWFファイルを制御したい。
そんな想いからはじまる今回のお話。
外部SWFを読み込むにはSWFLoaderやImageなどの方法がある。
Flex で読み込んだ SWF を制御 [ActionScript3.0]
ここを参考にSWFLoaderを使った方法で試みた。
しかし、
myLoader.content as MovieClip;
の部分でMovieClipへの変換がうまくいっていないらしくtraceしてみるとnullになっている。
MovieClipにしないと制御ができないーーー!!
ちなみに、myLoader.content自体をtraceすると[object AVM1Movie]と表示されている。
今度は、
ロードした外部swfを操作する for actionscript3.0
ここを参考にして、Loader関数を使った方法で試みてみる。
しかし、やはり
var mc:MovieClip = loader.content as MovieClip;
の部分でnullになる。
そこでAVM1MovieをMovieClipに変換する方法を探すのにすごい時間がかかったので備忘録で書き残しておく。
解決策はこれ
AVM1Movie Controller in Flex
まず以下のソースをForcibleLoader.asとして保存しておく。
引用URL:ForcibleLoader.as
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 package{import flash.display.Loader;import flash.net.URLRequest;import flash.net.URLStream;import flash.events.IOErrorEvent;import flash.events.SecurityErrorEvent;import flash.events.Event;import flash.utils.ByteArray;import flash.utils.Endian;import flash.errors.EOFError;public class ForcibleLoader{public function ForcibleLoader(loader:Loader){this.loader = loader;_stream = new URLStream();_stream.addEventListener(Event.COMPLETE, completeHandler);_stream.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);_stream.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);}private var _loader:Loader;public var _stream:URLStream;public function get loader():Loader{return _loader;}public function set loader(value:Loader):void{_loader = value;}public function load(request:URLRequest):void{_stream.load(request);}private function completeHandler(event:Event):void{var inputBytes:ByteArray = new ByteArray();_stream.readBytes(inputBytes);_stream.close();inputBytes.endian = Endian.LITTLE_ENDIAN;if (isCompressed(inputBytes)) {uncompress(inputBytes);}var version:uint = uint(inputBytes[3]);if (version <= 10) {if (version == 8 || version == 9 || version == 10){flagSWF9Bit(inputBytes);}else if (version <= 7) {insertFileAttributesTag(inputBytes);}updateVersion(inputBytes, 9);}loader.loadBytes(inputBytes);}private function isCompressed(bytes:ByteArray):Boolean{return bytes[0] == 0x43;}private function uncompress(bytes:ByteArray):void{var cBytes:ByteArray = new ByteArray();cBytes.writeBytes(bytes, 8);bytes.length = 8;bytes.position = 8;cBytes.uncompress();bytes.writeBytes(cBytes);bytes[0] = 0x46;cBytes.length = 0;}private function getBodyPosition(bytes:ByteArray):uint{var result:uint = 0;result += 3; // FWS/CWSresult += 1; // version(byte)result += 4; // length(32bit-uint)var rectNBits:uint = bytes[result] >>> 3;result += (5 + rectNBits * 4) / 8; // stage(rect)result += 2;result += 1; // frameRate(byte)result += 2; // totalFrames(16bit-uint)return result;}private function findFileAttributesPosition(offset:uint, bytes:ByteArray):uint{bytes.position = offset;try {for (;;) {var byte:uint = bytes.readShort();var tag:uint = byte >>> 6;if (tag == 69) {return bytes.position - 2;}var length:uint = byte & 0x3f;if (length == 0x3f) {length = bytes.readInt();}bytes.position += length;}}catch (e:EOFError) {}return NaN;}private function flagSWF9Bit(bytes:ByteArray):void{var pos:uint = findFileAttributesPosition(getBodyPosition(bytes), bytes);if (!isNaN(pos)) {bytes[pos + 2] |= 0x08;}}private function insertFileAttributesTag(bytes:ByteArray):void{var pos:uint = getBodyPosition(bytes);var afterBytes:ByteArray = new ByteArray();afterBytes.writeBytes(bytes, pos);bytes.length = pos;bytes.position = pos;bytes.writeByte(0x44);bytes.writeByte(0x11);bytes.writeByte(0x08);bytes.writeByte(0x00);bytes.writeByte(0x00);bytes.writeByte(0x00);bytes.writeBytes(afterBytes);afterBytes.length = 0;}private function updateVersion(bytes:ByteArray, version:uint):void{bytes[3] = version;}private function ioErrorHandler(event:IOErrorEvent):void{loader.contentLoaderInfo.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR));}private function securityErrorHandler(event:SecurityErrorEvent):void{loader.contentLoaderInfo.dispatchEvent(new SecurityErrorEvent( SecurityErrorEvent.SECURITY_ERROR));}}}
使い方としては、まずこのASファイルをimportします。
最初使い方を勘違いしていた私は
とすれば、importできると勘違いしていました。
このままやるとネストできませんっておこられます。
なので、普通に
import ForcibleLoader;
とかいておきましょう。
ちなみに同じフォルダにこのASファイルがあることが前提です。
そんでいざ実践。
SWFLoaderにmyLoaderとIDをつけておいてScriptに以下のソースを書く。
12345678910111213141516 import ForcibleLoader;private var loader:Loader;private var mc:MovieClip = new MovieClip();private var swfURL:String = "test.swf"; //ここにswfファイルのアドレスを書いとくprivate var libMC:MovieClip = new MovieClip();private function init(): void {var loader:Loader = new Loader();loader.contentLoaderInfo.addEventListener(Event.COMPLETE, swfComplete);var fLoader:ForcibleLoader = new ForcibleLoader(loader);fLoader.load(new URLRequest(swfURL));myLoader.addChild(loader); //ここでSWFLoaderに読み込んだSWFファイルを表示させる}private function swfComplete(event:Event):void{this.mc = event.currentTarget.content as MovieClip;trace( this.mc );}
やってみたらみごと[object MovieClip]とでてくれましたー!
これでようやく読み込んだSWFファイルの制御をすることができます。
Adobe Flex Builder Standard 3.0 日本語版 Windows/Macintosh版