Nevill’s Blog

blog my living stuff

  • February 2008
    M T W T F S S
    « Sep   Apr »
     123
    45678910
    11121314151617
    18192021222324
    2526272829  

Flash 9 中如何使用 Loader 加载

2月12日, 17:24

源码下载

做一个 Flash 程序,要实现一个 loading 过程,当加载一个比较大的外部资源,要显示加载进度,当外部资源全部都加载到本地播放器(Flash Player)以后,就开始播放。

下面是装载的完整过程:(以源码中的文件为例)
1)Player 装载 LoaderTest.swf,并产生相应的 LoaderInfo (可以通过在 LoaderTest 中访问 this.loaderInfo 属性得到)
2)LoaderTest 中使用 flash.display.Loader 对象调用 load 方法进行装载,装载的过程中会产生 open / progress / init / complete 几个事件,如果发生读取错误,会产生 ioError 事件
3)loader 装载完成以后,可以使用 loader.content 来访问被加载的影片(SimpleMovie.swf),使用 loader.contentLoaderInfo 来访问 SimpleMovie.swf 的 LoaderInfo 类的实例对象(即:这个时候在 SimpleMovie 里面访问到的 loaderInfo 属性与 LoaderTest.loader.contentLoaderInfo 是同样一个对象)

装载完成以后整个关系图可以如下表示:(图片来自 Adobe Flex Laugnage Reference

在实际使用 loader 的过程中遇到了一个小小的问题:装载比较大的 swf 时,往往没有完全装载成功,影片剪辑就开始播放了。

要看到这个效果需要在 IDE 中编译执行 LoaderTest.fla,在 Test Movie(快捷键 Ctrl + Enter)打开的 Flash Player 中从 View 菜单选择 Download Settings,设置一个比较慢的下载速度,比如 56K(4.7KB/S),然后再从 View 菜单中选一次 Simulate Download(快捷键还是 Ctrl + Enter),这样,我们看到的效果是,进度条到了 100% 以后就立马跳出来的是 SimpleMovie 里面的 Over! 画面了。从 Flash IDE 的输出我们看到这样的执行顺序:Open -> Progress -> Init -> Complete (在我的机器上,Init 大概是发生在 Progress 到了 8% 左右的时候)。

既然原因找到了,要解决这个问题的办法也很简单,修改 movieInit 这个方法,将 movieHolder.stop(); 前面的注释去掉

  1. protected function movieInit(event:Event):void {
  2. trace("init");
  3. movieHolder = MovieClip(loader.content);
  4. //设定当前 fps 同被加载进来的 .swf 相同
  5. stage.frameRate = loader.contentLoaderInfo.frameRate;
  6.  
  7. //看看取消注释后有什么变化
  8. //movieHolder.stop();
  9. }

再重新编译执行一下,就可以看到正确的效果了。

仔细看了一下 Adobe 的参考文档,里面对 Loader 的 init 事件说明大概是这样的:(翻译自 LoaderInfo 参考手册)
当被加载对象的所有属性和方法都能被访问到的时候,就产生该事件。要产生这个事件必须同时满足下列两种情况:
1)被加载的 DisplayObject 对象(本代码中的 SimpleMovie.swf,对于 LoaderTest 来说就是 loader.content)的所有属性都能被访问
且这个 DisplayObject 关联的一个叫做 loaderInfo 对应的 LoaderInfo 对象能被访问到(我的理解,能被访问到就是不为空)
2)这个 DisplayObject 里面所有子对象都被构造好、准备就绪了

也就是说,当 LoaderTest 中的 loader.contentLoaderInfo 和 loader 的其它的一些属性能被访问了,这个 contentLoaderInfo 就迫不及待的发出了 init 的信号,而此时,装载的过程并没有真正完成,还有很大一部分内容都没有被加载呢。真正加载完成、一个字节都没有漏掉的时候应该是 complete 这个事件发生的时候,只有在这个时候,被 loader 装载的 swf 之中每个对象、每个属性才能被真正访问到。

如果,我们把 stage.addChild(movieHolder) 这句从 loadComplete 移到 movieInit 里面来,我们可以看到 Flash 的边装载边播放的特性。即在 init 发生以后, SimpleMovie 就开始从第一帧开始播放了,此时的 Progress 大概在 8% 左右。

不过,一般情况下不要利用这个特性这么做。因为,在项目实践中,Tiger 发现被事先装载的部分可能是音乐,这样会出现音乐先播放,而画面跟不上的情况。

写这篇之前当然进行了一些搜索工作,找到一些文章说明 Flash 9 以前版本的 Loader 搞反了 init 和 complete 这两个事件,有兴趣可以读一下。
参考阅读:
1)http://www.awflasher.com/blog/archives/468
2)http://whatdoiknow.org/archives/001982.shtml

添加评论

名称
(required)

电子邮件 (不会显示出来)
(required)

你的网站地址

  • :em01:
  • :em02:
  • :em03:
  • :em04:
  • :em05:
  • :em06:
  • :em07:
  • :em08:
  • :em09:
  • :em10:
  • :em11:
  • :em12:
  • :em13:
  • :em14:
  • :em15:
  • :em16:
  • :em17:
  • :em18:
  • :em19:
  • :em20:
  • :em21:
  • :em22:
  • :em23:
  • :em24:
  • :em25:
  • :em26:
  • :em27:
  • :em28:
  • :em29:
  • :em30:
  • :em31:
  • :em32:
  • :em33:
  • :em34:
  • :em35:
  • :em36:
  • :em37:
  • :em38:
  • :em39:
  • :em40:
  • :em41:
  • :em42:
  • :em43:
  • :em44:
  • :em45:
  • :em46:
  • :em47:
  • :em48:
  • :em49:
  • :em50:
  • :em51:
  • :em52:
  • :em53:
  • :em54:
  • :em55:
  • :em56:
  • :em57:
  • :em58:
  • :em59:
  • :em60:
  • :em61:
  • :em62:
  • :em63:
  • :em64:
  • :em65:
  • :em66:
  • :em67:
  • :em68:
  • :em69:
  • :em70:
  • :em71:
  • :em72: