打印

[AS3] 【从AS2到AS3之三】全新的加载(Loading)机制

做一个loading预加载的效果相信大家都已经非常熟悉了,不管是用onEnterFrame还是setInterval,还是更高级的MovieClipLoader。可当开始用AS3的时候,便连一个最简单的loading都无从下手了。是不是AS3中的loader更加复杂,难以控制呢。其实不是的,在AS3中引入了一个全新的类LoaderInfo,这个类可作用于任何的可显示对象(display object),这个对象里包含了加载过程检测、加载地址、加载对象的内容、加载对象总字节数(和加载过程中的字节数)、加载对象的宽度高度等等非常多的内容(内容太多了,更多的大家可以去看帮助)。

有2种方式可以访问LoaderInfo对象:
1)访问flash.display.Loader对象的contentLoaderInfo属性;
2)任何一个可显示对象(display object)都有loaderInfo属性;

注意:每个SWF文档的主类的实例有loaderInfo属性,每个Loader有loaderInfo属性,同时它有一个contentLoaderInfo属性,通过这个属性你可以访问到Loaded对象的loaderInfo。具体可以看下图:


下面还是老习惯,来例子示范。
先来一个loading外部文件的例子:
复制内容到剪贴板
代码:
var request:URLRequest = new URLRequest("flashrek.swf");
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, loadProgress);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
function loadProgress(event:ProgressEvent):void {
    var percentLoaded:Number = event.bytesLoaded/event.bytesTotal;
    percentLoaded = Math.round(percentLoaded * 100);
    trace("Loading: "+percentLoaded+"%");
}
function loadComplete(event:Event):void {
    trace("Complete");
}
loader.load(request);
addChild(loader);
这里要注意loader的load方法只接受URLRequest对象作为参数;另外就是ProgressEvent类,比较简单,看帮助就好了。

    关于自身loading部分,可以利用SWF文档的主类的实例自身的loaderInfo属性来做。方法可以参看一下我在15楼的代码。
更多具体信息可以参看我的blog:http://www.flashrek.com/article.asp?id=10。有什么建议大家都可以提出来,一起探讨。

另外,大家可以看看Preloaders in AS3:http://www.bit-101.com/blog/?p=946

[ 本帖最后由 flashlizi 于 2007-5-16 09:53 编辑 ]
附件: 您所在的用户组无法下载或查看附件,您需要注册/登录后才能查看!
本帖最近评分记录
  • mirycat 威望 +2 原创内容 2007-5-12 23:33
不错.在flex2.0.1里这个简单的自身loading好像不起作用.不知道为什么?
我用的是flash cs3,flex2里有可能不一样。

TOP

认证您的手机,获得手机认证图标, 更多手机认证的好处
不错 收下了
http://www.5ucai.com
无忧素材网
这样的类不是很易让大家共享么?
大连

TOP

“每个SWF文档是通过loaderInfo属性访问此对象的;每个Loader对象是通过contentLoaderInfo属性访问此对象,而Loader的加载对象Loaded则是通过loaderInfo属性访问次对象的。”

loaderInfo访问的不是对象,是对象的一些与加载有关的附加信息。
Loader一样是由loaderInfo访问自己的附加信息
contentLoaderInfo访问的是Loader加载的内容的附加信息

直观点说,Loader是一个加载容器,要加载的内容将是它的child
做Loading时需要检测的是内容的加载状态,而不是容器的
所以用 Loader.contentLoaderInfo (加载的内容的加载信息) 而不是 Loader.loaderInfo (容器自己的加载信息)

TOP

另外关于自身的加载,因为代码是在swf加载完成后才会执行的
所以楼主这种写法是无效的——当检测代码执行时swf已经完成加载了
关于AS3的自身加载请看这里
http://www.bit-101.com/blog/?p=946

TOP

答eidiot:
1、首先我的这段话“每个SWF文档是通过loaderInfo属性访问此对象的;每个Loader对象是通过contentLoaderInfo属性访问此对象,而Loader的加载对象Loaded则是通过loaderInfo属性访问次对象的。”中的访问此对象,这个对象是指的loaderInfo对象。你所说的”是对象的一些与加载有关的附加信息“,这些附加信息正是loaderInfo对象的内容。大家用trace(loaderInfo)和trace(loader.contentLoaderInfo)看一下就明白了。

2、关于自身加载。我的代码没问题。如你所说,当然前提是这段加载的代码必须在所有内容加载前执行。处理方式和as1,as2是一样的。把loader代码放到单独的loader场景中,而不是主场景中。至于bit-101的方法,我还没看,待会学习学习。

TOP

1, 我的意思是说 Loader 有自己的 loaderInfo ,Loader 的 contentLoaderInfo 实际上指向的是它加载的内容的 loaderInfo,重新组织你的话应该是
"每个Loader对象是通过loaderInfo属性访问此对象,而Loader的加载对象Loaded则是通过loaderInfo属性或者加载它的Loader的contentLoaderInfo属性访问此对象的"
2,你放在哪里都是没用的,AS3 的“自加载”是不能以这种方式实现的。

[ 本帖最后由 eidiot 于 2007-5-11 21:09 编辑 ]

TOP

引用:
原帖由 eidiot 于 2007-5-11 20:13 发表
1, 我的意思是说 Loader 有自己的 loaderInfo ,Loader 的 contentLoaderInfo 实际上指向的是它加载的内容的 loaderInfo,重新组织你的话应该是
"每个Loader对象是通过loaderInfo属性访问此对象,而Loader的加载 ...
eidiot:101的上面都是E文,我英语太差了,可能理解的有问题,按他写的代码做的实验老有问题,你能不能写个出来啊。load的问题我是搞不清除啦。

TOP

这个东西AW正在研究,说是“稍后介绍”,等他的结果吧
我比较懒 :-)

另外关于 contentLoaderInfo 楼主的代码是没问题的,只是概念的介绍上有点偏差,还是搞清楚了好

[ 本帖最后由 eidiot 于 2007-5-11 20:43 编辑 ]

TOP

引用:
原帖由 eidiot 于 2007-5-11 20:13 发表
1, 我的意思是说 Loader 有自己的 loaderInfo ,Loader 的 contentLoaderInfo 实际上指向的是它加载的内容的 loaderInfo,重新组织你的话应该是
"每个Loader对象是通过loaderInfo属性访问此对象,而Loader的加载 ...
1、Loader只有contentLoaderInfo属性,并没有loaderInfo这个属性。不过,我的说明可能不太清楚,要修改下。
2、经过我的实验,是可行的。

[ 本帖最后由 flashlizi 于 2007-5-11 21:31 编辑 ]

TOP

Loader 的 contentLoaderInfo 其实和 Loader 没关系,指向的是另一个DisplayObject (Loader加载的对象)的 LoaderInfo 。加载完成之后可以使用Loader的 content 属性访问这个加载的对象,但是在加载完成之前 content.loaderInfo 是无法访问的(加载完成之前content都是null,访问还不存在的content的loaderInfo会报错),所以只能通过 Loader.contentLoaderInfo 来间接的访问 —— contentLoaderInfo 其实就是在 content 加载完成之前访问 content.loaderInfo 的一个通道而已(加载完成之后可以trace一下 loader.contentLoaderInfo == loader.content.loaderInfo,输出为 true)。

[ 本帖最后由 eidiot 于 2007-5-11 23:06 编辑 ]

TOP

引用:
原帖由 flashlizi 于 2007-5-11 21:18 发表
1、Loader只有contentLoaderInfo属性,并没有loaderInfo这个属性。不过,我的说明可能不太清楚,要修改下。
这个。。。。。。
楼主玩笑开大了,只要是 DisplayObject 就有 loaderInfo 属性。当然,是继承来的,你要是只看 Loader 类定义的属性是找不到的。点开继承属性就能找到了。另外使用代码提示检测方法、属性是否存在是最简便快捷的方法

TOP

申明一点:我的所有AS3的文章都是基于Flash CS3 IDE,在flex下不保证有效。
刚稍微看了下bit-101上的文章,这是基于flex的,flex并没有timeline,当然无法用我这个。
至于实验,你看看这个是不是preloading效果:
http://www.flashrek.com/PreLoader.html

我在这个swf里只加了一个mp3做测试。mp3放在第二帧。Document Class代码为:
复制内容到剪贴板
代码:
package flashrek.example{
    import flash.display.MovieClip;    
    import flash.events.Event;
    import flash.events.ProgressEvent;
    import flash.display.LoaderInfo;
    import flash.text.TextField;
    public class PreLoader extends MovieClip {
        var loadText:TextField=new TextField();
        public function PreLoader() {
            this.loaderInfo.addEventListener(ProgressEvent.PROGRESS, loadProgress);
            this.loaderInfo.addEventListener(Event.COMPLETE, loadComplete);
            addChild(loadText);
        }
        private function loadProgress(evt:ProgressEvent):void {
            var perLoaded:Number = evt.bytesLoaded/evt.bytesTotal;
            perLoaded = Math.round(perLoaded * 100);
            loadText.text = "Loading: "+perLoaded+"%";
            //trace("Loading: "+perLoaded+"%");
        }
        private function loadComplete(evt:Event):void {
            //trace("Complete");
            loadText.text="Complete";            
        }
    }
}
[ 本帖最后由 flashlizi 于 2007-5-11 22:19 编辑 ]

TOP

引用:
原帖由 eidiot 于 2007-5-11 21:58 发表

这个。。。。。。
楼主玩笑开大了,只要是 DisplayObject 就有 loaderInfo 属性。当然,是继承来的,你要是只看 Loader 类定义的属性是找不到的。点开继承属性就能找到了。另外使用代码提示检测方法、属性是 ...
恩,这个是我错了。刚才tracel错了一个没有addChild的loader,又看loader类里没有loaderInfo属性,就下错误结论。抱歉。

[ 本帖最后由 flashlizi 于 2007-5-11 22:14 编辑 ]

TOP

引用:
原帖由 flashlizi 于 2007-5-11 22:02 发表
申明一点:我的所有AS3的文章都是基于Flash CS3 IDE,在flex下不保证有效。
刚稍微看了下bit-101上的文章,这是基于flex的,flex并没有timeline,当然无法用我这个。
至于实验,你看看这个是不是preloading效 ...
你的那个实验是不行的,和那个mp3文件比起来,代码很快就加载完可以执行了,所以貌似有效。但是实际开发中是不会有这种情况的。
目前解决自加载问题的两种方案:
1,在文档类之前运行preload代码,如bit101的解决方案。
2,文档类(主swf)只包含少量代码,其它内容外部加载。
我个人倾向第二种,但是这意味着将放弃文档类的一些好用的特性。

你那种方法是绝对不行的——如果你用AS3。国内外这么多人挖空心思琢磨AS3的 preLoader ,不是无聊消遣的。
AW说要研究,在他或者楼主你得出结论之前建议还是暂时删掉关于自加载部分的代码。另外关于 contentLoaderInfo 最好还是描述清楚一点(参考我13楼的回复),以免误导初学者。

[ 本帖最后由 eidiot 于 2007-5-11 22:45 编辑 ]

TOP

To eidiot:Document Class是优先于主时间轴代码执行初始化的。把其他类都取消设置export in first frame,即保证第一帧不能放置其他内容。按照AS2中的解决办法难道不行么。或者你举个例子看看,谢谢。

TOP

首先,请抛弃“时间轴”的概念。其次,请忘掉“AS2中的解决办法”。这是我对学习AS3的建议。
当你真正使用AS3进行开发的时候就会明白了

[ 本帖最后由 eidiot 于 2007-5-12 09:26 编辑 ]

TOP

这几天都没时间来研究这个问题。今天看了下101 blog的“Preloaders in AS3”文章。有意思的是,他的解决办法的核心竟然是利用frame标签产生一个two-frame(2帧)的swf(因不了解flex,修改先前错误)。剩下的preload思想就是把其他的类都放在第二帧,在第一帧做preload。

另外,本人不同意eidiot的“抛弃“时间轴”的概念”的说法。学习AS3要尽量弱化timeline的概念,但不等于抛弃。至于得出抛弃这个概念说法的,我想一定是一个flex开发工程师,而非flash开发工程师。以后timeline确实会用得越来越少,但我觉得在AS3中它仍然有着非常好的作用(flex开发着就用不着了)。

还有本人认为我在15楼中的preloader在flash cs3中是可行的。不过关键是,要把其他所有类等内容都不能export in first frame。至于flash内部的核心类,也要确保不在第一帧导出即可(在publish的AS设置里的export classes in frame项设为2或者其他合适的值即可)。

[ 本帖最后由 flashlizi 于 2007-5-14 19:46 编辑 ]

TOP

1,首先,请抛弃“时间轴”的概念。其次,请忘掉“AS2中的解决办法”。这是我对学习AS3的建议。
MovieClip依然是重要的类型,很多动画、状态演示离不开时间轴
但是结构的设计上要学好事件机制、MVC/MVP

2,产生一个two-frame(2帧)的swf在flex里是不可能达到的事实?无语。。。。。。

3,关于preLoader我前面纯是以经验判断,并没有实际测试,说的太绝对了,抱歉。如果你确信自己的方案可行尽可以发出来。最后只提醒三点:
a, 把所有类都推到第二帧或更后导出,文档类是否可以保证正常运行。
b, 把其它类和元件放在第二帧或更后,文档类调用时是否可保证其被正常初始化,所有方法可正常调用。
c, 确认Loading是否完全有效,Loading代码执行时SWF究竟已经下载了多少

[ 本帖最后由 eidiot 于 2007-5-14 19:57 编辑 ]

TOP

对于flex: as3 project,可以用bit101的类;

注意的是,你自己的类里在构造过程中不再能引用到stage,而可以把stage作为参数传进来就可以了

TOP

太精彩了!!!!
可惜刚刚才看到,不知道现在各位大哥有没有统一的关于preloading的认识了吗?

TOP

很久没有这样精彩的前辩论了.......哈哈....

这种气氛很好, 不管谁对谁错,  能勇于站出来说些话, 都是互相学习的好兆头..呵呵...

对于preLoader, 期待中......
www.riaHome.cn

TOP

学习中。。。

TOP

我想做整个Swf的预载,不是载入MovieClip之类的,在AS3里有什么比较简单的方法?

TOP

讨论出结果了吗?

TOP

美工- =

我是一个美工 像要一个类似一个as 2.0那样写在第一帧上的 简便方法有吗   
你们讲的太复杂了    我看不太懂、
如过我讲的太肤浅 。。失礼了

TOP

我还没研究 loading的问题
AS3 中 都是以一个 main.as 主类文件开始的
用文档类的话,主场景的时间轴上是不能写AS 的

这样的话 对于整个站点的LOADING  就有点迷糊了

TOP

好地作品要顶起来 面对对象真是一个难地转换
FL网站   http://www.Flsky.Net

TOP