Flash/flex中载入图片等资源文件的几种方法
这篇文章描述了Flash/flex中载入图片等资源文件的几种方法,目前Flash最新的版本是Flash Pro CS4,CS5快要发行beta版。那么,我们来具体的看一看如何输出SWC文件,并通过[Embed]元标签来获得资源的方法。
背景
如果,你正在创建一个应用程序,一个游戏,或者一个网站。在设置你的Flash项目时,有两种选择。1 你可以创建一个FLA文件,指定一个文档类进行编码。或者2,你也可以选择Flash/Flex Builder,FDT,Flash Develop等,创建一个Flex或者AS3项目,然后使用Flex SDK编译它。几乎每一次,我都选择后者,因为后者增强了程序的可靠性,而且编译速度更快。
即使你选择了使用Flash Pro创建并编译FLA文件,你也可能会在Flash Builder或者其他IDE中修改代码。但问题是,之前你使用的是Flash Pro编译,接着要使用Flex SDK进行编译。写这篇东西的目的是,当我们使用Flex SDK编译Flex或者AS3项目时,我们如何通过FLA载入资源的。
我尽可能的将我所知道的写出来,但一定会有些技巧和窍门,甚至是方法,是我所不知道的。如果你发现任何错漏的地方,请一定让我知道,我会尽快修正。(译注:直接跟帖好了,加威望加银子^_^)
为什么非要是FLA文件?
你可能已经知道,可以将PNG图像,SVG和其他文件类型嵌入到你的类中,并且永远也不需要通过FLA文件获取图形。当涉及到动画,你可以使用 TweenLite或者GTween。但是涉及到帧动画,角色动画,或者干脆是按钮和手绘的元件时,你可能需要使用Flash Pro上强大的时间轴,图形和动画工具去创建元件,并使它们动起来,这时就需要FLA了。
这时候你该问问自己,如果我的项目不使用Flash Pro编译,那么如何从FLA中获取资源导入到项目中去?
工作流程
这里有五种将FLA中的资源嵌入到Flex或者纯AS3项目中的方法。为了照顾通用性,我已经排除了那些只适用于MXML的方法。
1 通过FLA发布SWC
这个方法涉及到库元素链接类,你必须在元素链接中写明类的路径,例如“com.package.MyClass”。接着你必须选择在“Flash发布设置 面板中”勾选“导出SWC”,然后打开“AS3设置面板”勾选“自动申明舞台实例”选项以避免错误。最后,添加所有必须的类路径以避免在编译的时候出错。
当你发布SWF文件时,SWC文件也会被发布到同个文件夹中。你将这个SWC文件加入到你的AS3项目中,就可以通过编码使用里面的类/元件了。
优点:
这个方法保持了时间轴上的as代码,适合复杂的,嵌套或者多个状态的动画。
缺点:
当你改变元件链接的类时,你必须重新编译整个FLA文件。这意味着又要打开Flash,导出SWC文件,再导回Flash Builder,刷新项目才能够重新引用新的SWC文件,最后再重新编译整个项目。
你还必须确保,元件链接的类不在项目的源目录(或项目映射的源代码目录)。如果你不这样做,你可能看不到你的图形/动画,因为Flex链接器会因为编译顺序而寻找类别定义,从而忽略SWC。
你必须添加所有必要的类路径进FLA。
Flash builder将不会报错,而且你也不能通过Ctrl/Cmd+左键点击跳到源文件中。
你不能立即在舞台上使用它们,解决办法是相当痛苦的(见http://richardleggett.co.uk/blog ... meline_items_in_as3)。
总结:
虽然这是保持时间轴代码的唯一方法,但缺点使它变得不直观,同时令人沮丧。如果谁能提供一个改善的方法,我会请你喝啤酒。
2 在申明类之前使用[Embed]标签
- package my.package {
- [Embed(source="assets/some.swf", symbol="SymbolName")]
- public class MyClass {
- // code
- }
- }
在 这里我们仅仅使用一个FLA生成一个SWF来存储我们的元件。FLA中的元件没有做任何类绑定。库中只是充满了MovieClip。在我们的类文件中,我 们添加[Embed]标签,接着绑定SWF文件中的元件。所以,当我们创建这个类的实例时,我们就能得到元件库中的图形。
优点:
你不必重新编译FLA文件,除非你改变FLA中的图形。
你可以在编码环境上花更多的时间,而不是在不停的来回捣腾。
你可以实时的获得编译错误,因为代码不是来自一个SWC文件。
缺点:
它把你元件中时间轴上的AS代码剥离了,如果你的元件是一个动画,而且有几帧停止。那么你的动画就会不停循环。解决办法是为所有要停止 的帧使用addFrameScript(5, stop)。甚至使用大量的帧标签作为“元标签”进行代码替换(又自成一篇http://code.google.com/p/as3-asset-modifier/)
3 [Embed]标签在类属性前声明
- [Embed(source="assets/some.swf", symbol="MySymbol")]
- private var MySymbol:Class;
- // later on in a function...
- var myInstance:Sprite = new MySymbol();
昂,你可能已经猜到,这是一个结构更基础的方法。它适用于简单的图形,多帧MovieClip,或者你基于MovieClip的扩展,并让它停止。
采用这种方法,你要么实例化一个SpriteAsset(扩展自Sprite),要么是一个MovieClipAsset(扩展自MovieClip)。你不能将它转变为一个自定义类,对于一个元件来说,这只是一个联络象征。
4 用[Embed]标签载入整个SWF
这里还有另外一个可用的属性可以提供给Embed元标签,就是mimeType。如果你删除元件属性,并让mimeType=” application/octet-stream” 。将会嵌入整个SWF,并且保持库中的类关联。
当你使用这种方法从一个SWF中嵌入一个元件,你可以使用Loader去获得类,像这样:
- [Embed(source="assets/some.swf", mimeType="application/octet-stream")]
- private var MySWF:Class;
- // within a method
- var bytes:ByteArray = (new MySWF() as ByteArray);
- var loader:Loader = new Loader();
- loader.loadBytes(bytes, new LoaderContext(false, ApplicationDomain.currentDomain));
- // wait for loader to dispatch Event.COMPLETE and...
- var myClass:Class = loader.contentLoaderInfo.applicationDomain.getDefinition("com.package.MyClass");
- var myInstance:DisplayObject = new myClass();
- // myInstance is now an instance of the class linked to it
优点:
这是一个很棒的方法去获得资源而不必重新编译FLA
缺点:
我想你会同意。如果你有很多元件,或者很多嵌套 了很多其他东西的元件,这种方法就不是一个理想的选择。即使库能提供很大的帮助。但是……它没有严格定义类型。
5 运行时载入一个SWF
这也许是最古老的一个方法。在运行时加载SWF可以使用applicationDomain.getDefinition() 获得元件/类,和方法3有点类似。如果你已经熟悉了getDefinition()方法,那问题就简单得多了。但你针对的只是一个特定的SWF中的类。
优点:
适用于很少改变的内容,比如字体
缺点:
神奇的字符串:定义一个字符串常量不会有别的什么作用,如果你改变FLA中的字符串,你的常量就变得毫无意义。并且你只有在那片代码执行的时候才能才会发现。
你必须从FLA中导出你的SWF,或使用其他技术。这意味着你会遇到其他的一些问题。
反馈
那么你选择哪个方法?也请说明你的项目类型:应用软件,游戏,网站;也有可能在构建应用的时候根本不会遇到这些问题。
你也许会考虑如何更简单的使用Flash CS5生成iPhone应用,这将影响你决定使用何种方法。
总的来说,我觉得每一种方法都有缺陷,所以要慎重做出选择。目前我还没有找到一个完美的方案。能够使用Flash Pro加快处理游戏资源,在舞台上放置资源,在时间轴上做动画……但这样做弊大于利,把读取资源的工作搞复杂了。我希望在未来能加强工具间的联系,或许能 通过一个新的文件格式来实现