9RIA.com天地会 - 论坛

返回列表 发帖

天地培训

9RIA天地会官方培训机构

Adobe官方认证培训中心

老生长谈关于Loading的讨论

我是个新手,面对as3的Loading有点无从下手,看了很多的思路,但是都不知道哪个好,和大家讨论一下,试图得到一个完整的思路。
现在网上关于as3的loading的文章就那么几篇,文章附于最后
我们讨论一下什么是最好的解决办法:
从这三篇来看
思路大致是这样的
1、外载其它的文件没话说,使用Loader类,loaderInfo.addEventListener(ProgressEvent.PROGRESS,你的处理函数)
2、关于自身的loading,则分为两种观点,一种是使用一个load容器,不管什么都往其中加载,不存在main自身加载的问题。还有一种就是蓝色理想(第三篇)文章中说的可以利用SWF文档的主类的实例自身的loaderInfo属性来做。

至于在下载字节的计算倒是没什么好说的
function 函数(事件名称: ProgressEvent){
var loadedPercent:int=事件名称.bytesLoaded/事件名称.bytesTotal*100;
trace(loadedPercent)
}



好我们首先讨论简单的,load容器的loading

***********************************
下面这个例子借用了蓝色理想(第三篇)中的例子


//这个例子是加载外部的文件,注意load方法只能接受URLRequest文件
var request:URLRequest = new URLRequest("flashrek.swf");
//定义一个loader
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文件和一个main文件

(未完待续。。。今天有点事,呵呵,随后补齐,先发了站个位置)

===============================================

[ 本帖最后由 3118743 于 2008-7-21 13:52 编辑 ]

天地人才库
第一篇:
==================
AS3通俗教程---AS3自身loading制作
我也来学着写教程  ,希望能对大家有所帮助,若发现问题欢迎指正!

先说主场景舞台有内容的项目(如MV)的做法:
有人问是不是new一个loader,然后loader.load(this),其实根本没这么麻烦,很简单,在文档类构造函数里写上:loaderInfo.addEventListener(ProgressEvent.PROGRESS,你的处理函数)就行了,处理函数这样写:
function 你的处理函数(e : ProgressEvent){
trace(e.bytesLoaded/e.bytesTotal);
}
就行了,简单吧!
再说界面代码分离项目(主舞台内容靠AS生成)的做法:
这个容易出错,常见错误是按照上面MV的loading一样做,这样的结果是loading一出来就是100%,
原因在于界面代码分离项目主时间轴通常只有一帧,而flash会默认在第一帧导出类,并在此之后调用文档类的构造函数,也就是说progress事件的侦听是在加载完成后才起作用,当然看不到进度了!

解决方法一,双文件法(代码见回复),这种方法实际是绕过去了:
建立loader.as, 建loader.fla并设loader为文档类
建立main.as, 建main.fla并设main为文档类
在loader.as中
    new一个Loader实例 loader,并用load方法载入main.swf
    在 loader.contentLoaderInfo上添加progress和complete侦听
    在progress处理函数中更新textField,并在complete处理函数将loader.content添加到舞台
在main.as中
    构建舞台内容
解决方法二,双帧法,这才是真正解决:
但有个小遗憾是主时间轴是2帧,但已经不错了,呵呵
建立loader.as,再建立fla文件,保证主时轴有两帧且都为关键帧
在fla中:
    建立一个空Mc,将此Mc拖到主场景的第二帧

    双击编辑空元件,再将此元件的时间轴改为两帧且都为关键帧,进入第二帧,将库中所有链接到类的元件拖到舞台

    将所有链接到类的元件的链接属性中的“在第一帧导出”取消掉:
在loader.as中
    建立textField并推入舞台, 构造函数中为loaderInfo添加progress和complete侦听
    在progress处理函数中更新textField,并在complete处理函数中再添加enter_frame侦听
    在enter_frame处理函数中构建舞台内容,并移除enter_frame侦听,也就是说让enter_frame处理函数执行一次就可以了

无效代码:
复制内容到剪贴板代码:
package {
import flash.display.MovieClip;
import flash.events.*;
import flash.text.*;
//////
public class loader extends MovieClip {
  var ttf=new TextField();///建立一个TextField实例
  public function loader() {
   addChild(ttf);/////////将TextField实例推到舞台
   loaderInfo.addEventListener(ProgressEvent.PROGRESS,progressHandler);///当进度变化时更新TextField实例的text属性
   loaderInfo.addEventListener(Event.COMPLETE,completeHandler);///////////当载入完成后显示内容
  }
  function progressHandler(e:ProgressEvent) {
   ttf.text=e.bytesLoaded*100/e.bytesTotal;
   trace(ttf.text);
  }
  function completeHandler(e:Event) {
   removeChild(ttf);//////////////载入完成后移除进度显示文本
   addChild(new main());
  }
}
}
双文件代码-loader.as
复制内容到剪贴板代码:
package {
import flash.display.MovieClip;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.text.*;
import flash.events.*;
////
public class loader extends MovieClip {
  var mainLoader=new Loader();///建立一个Loader实例用于载入main.swf
  var ttf=new TextField();///////建立一个TextField实例用于显示载入百分比
  public function loader() {
   addChild(ttf);///////////////////////////////////////将TextField实例显示到舞台
   mainLoader.load(new URLRequest("main.swf"));/////////开始载入main.swf
   mainLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,progressHandler);///当载入进度变化时更新进度显示
   mainLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,completeHandler); //////////当载入完成后将main.swf加到舞台
  }
  function progressHandler(e:ProgressEvent) {
   ttf.text=(e.bytesLoaded*100/e.bytesTotal).toFixed(1);
  }
  function completeHandler(e:Event) {
   addChild(mainLoader.content);
  }
}
}
双帧代码-loader.as
复制内容到剪贴板代码:
package {
import flash.display.MovieClip;
import flash.events.*;
import flash.text.*;
import flash.net.*;
//////
public class selfloader extends MovieClip {
  var ttf=new TextField  ;//仍然建立一个TextField实例
  public function selfloader() {
   addChild(ttf);////////仍然将TextField实例推到舞台
   loaderInfo.addEventListener(ProgressEvent.PROGRESS,progressHandler);//仍然当进度变化时更新TextField实例的text属性
   loaderInfo.addEventListener(Event.COMPLETE,completeHandler);//////////仍然当载入完成后显示内容
  }
  function progressHandler(e:ProgressEvent) {
   ttf.text=e.bytesLoaded * 100 / e.bytesTotal.toFixed();
   trace(ttf.text);
  }
  function completeHandler(e:Event) {
   this.addEventListener(Event.ENTER_FRAME,enterframeHandler);//添加enter_frame侦听
   trace("载入完成");
  }
  function enterframeHandler(e:Event) {
   if (currentFrame == 1) {///////////////////////////////////////等于1或是2都可以,1更好
    stop();//////////////////////////////////////////////////其实这个stop()可以不加,加上更好
    removeChild(ttf);//////////////////////////////////////////////////仍然移除进度显示文本
    this.removeEventListener(Event.ENTER_FRAME,enterframeHandler);/////必须移除侦听
    addChild(new main  );
    trace("OK");
   }
  }
}
}


======================
第二篇:
======================
AS3.0新手必读-影片Loading
原代码说明:
1帧:
/*********************************
AS3.0 LOADING CODE
www.mhhf.net
MAGIC WING STUDIO
BY 2007-09-01
**********************************/
stop();
stage.scaleMode=StageScaleMode.NO_SCALE;
//设置舞台属性不跟随播放器大小而改变
stage.showDefaultContextMenu=false;
//屏蔽右键菜单
stage.frameRate=30;
//设置帧频为30
var stageW=stage.stageWidth;
var stageH=stage.stageHeight;
//取得舞台宽和高
var loadclip:MovieClip=new MovieClip();
//创建LOADING MC loadclip
this.addChild(loadclip)
//添加loadclip到舞台
var txt=new TextField();
//创建文本文件 txt
txt.autoSize=TextFieldAutoSize.CENTER;
//文本文件自适应大小并且居中显示
txt.text="AS3.0 Loading...";
txt.textColor=0x000000;
//设置文本颜色
txt.selectable=false;
//文本设置为不可选
txt.x=stageW/2-txt.width/2;
txt.y=stageH/2-txt.height/2;
//设置本文件放置于舞台中央
loadclip.addChild(txt);
//将文本实例txt添加到loadclip

var stgb=new Sprite();
stgb.graphics.lineStyle(1,0x000000,1);
stgb.graphics.beginFill(0xff0000,.5);
//采用单色填充,红色透明50%(.5)
stgb.graphics.drawRect(0,0,200,10);
stgb.graphics.endFill();
stgb.x=stageW/2-stgb.width/2;
stgb.y=txt.y+txt.height+5;
loadclip.addChild(stgb)
//绘制进度条底色并且添加到loadclip

var stg=new Sprite();
stg.graphics.lineStyle(1,0x000000,.5);
stg.graphics.beginGradientFill(GradientType.LINEAR,[0xff0000,0xffff00],[100,100],[0,255]);
//采用渐变填充 红--黄
stg.graphics.drawRect(0,0,200,10);
stg.graphics.endFill();
stg.x=stageW/2-stg.width/2;
stg.y=txt.y+txt.height+5;
loadclip.addChild(stg)
//绘制进度条并且添加到loadclip

this.loaderInfo.addEventListener(ProgressEvent.PROGRESS,loading);
//添加进度监听
this.loaderInfo.addEventListener(Event.COMPLETE,loaded);
//添加进度完成监听
function loading(eve) {
     var loadpre:int=eve.bytesLoaded/eve.bytesTotal*100;
     txt.text="影片载入"+loadpre+" %";
     stg.scaleX=loadpre/100;
}
//显示进度载入百分比-----
function loaded(eve) {
     txt.text="影片载入完毕!";
     if (framesLoaded == totalFrames) {
           removeChild(this.getChildAt(0));
           nextFrame();
     }
}
=====================
第三篇:
=====================
http://bbs.blueidea.com/thread-2744638-1-1.html
这篇我没有摘原文,因为有图片和附件需要在原来的帖子上看
=====================

[ 本帖最后由 3118743 于 2008-7-21 13:52 编辑 ]
1

评分人数

  • kafka

kafka 赐本贴 银子 + 10  诏曰: 总结的不错

TOP

<怕不够用,占一层备用。。。版主别删。。。谢谢>

TOP

好兄弟,讲义气!---by eko

踏上天地会荣耀之路!

 

申请舵主

加入掘金队

加入译林军

知识专题整理

 

咨询(QQ):

1442604479(小地)

 

很好,很强大,建议把代码加在code里面,现在这个样子看得很累
http://blog.crazypig.org/
欢迎光临我的blog

TOP

package {
        import flash.display.MovieClip;
        import flash.events.*;
        import flash.text.*;
        import flash.net.*;
        //////
        public class selfloader extends MovieClip {
                var ttf=new TextField;//仍然建立一个TextField实例
                public function selfloader() {
                        addChild(ttf);////////仍然将TextField实例推到舞台
                        loaderInfo.addEventListener(ProgressEvent.PROGRESS,progressHandler);//仍然当进度变化时更新TextField实例的text属性
                        loaderInfo.addEventListener(Event.COMPLETE,completeHandler);//////////仍然当载入完成后显示内容
                }
                function progressHandler(erogressEvent) {
                        ttf.text=e.bytesLoaded * 100 / e.bytesTotal.toFixed();
                        trace(ttf.text);
                }
                function completeHandler(e:Event) {
                        this.addEventListener(Event.ENTER_FRAME,enterframeHandler);//添加enter_frame侦听
                        trace("载入完成");
                }
                function enterframeHandler(e:Event) {
                        if (currentFrame == 1) {///////////////////////////////////////等于1或是2都可以,1更好
                                stop();//////////////////////////////////////////////////其实这个stop()可以不加,加上更好
                                removeChild(ttf);//////////////////////////////////////////////////仍然移除进度显示文本
                                this.removeEventListener(Event.ENTER_FRAME,enterframeHandler);/////必须移除侦听
                                addChild(new main  );
                                trace("OK");
                        }
                }
        }
}
上面的代码写的太罗嗦..该代码做到了加载完后跑下第二帧,所以也可以用.不必用加Event.ENTERFRAME事件,可以改成下面的:
注:上面的方法文档类初始化的时候没有停在第一帧(运行的时候其实是一直在跑主时间轴).下面的方法文档类构造时会执行这样的语句:this.stop();
package {
        import flash.display.MovieClip;
        import flash.events.*;
        import flash.text.*;
        import flash.net.*;
        //////
        public class selfloader extends MovieClip {
                var ttf=new TextField;//仍然建立一个TextField实例
                public function selfloader() {
                        addChild(ttf);////////仍然将TextField实例推到舞台
                        loaderInfo.addEventListener(ProgressEvent.PROGRESS,progressHandler);//仍然当进度变化时更新TextField实例的text属性
                        loaderInfo.addEventListener(Event.COMPLETE,completeHandler);//////////仍然当载入完成后显示内容
                }
                function progressHandler(erogressEvent) {
                        ttf.text=e.bytesLoaded * 100 / e.bytesTotal.toFixed();
                        trace(ttf.text);
                }
                function completeHandler(e:Event) {
                                (this.root as MovieClip).gotoAndStop(2);
                                (this.root as MovieClip).gotoAndStop(1);
                                loaderInfo.removeEventListener(ProgressEvent.PROGRESS,progressHandler);//仍然当进度变化时更新TextField实例的text属性
                                loaderInfo.removeEventListener(Event.COMPLETE,completeHandler);//////////仍然当载入完成后显示内容
                                stop();//////////////////////////////////////////////////其实这个stop()可以不加,加上更好
                                removeChild(ttf);//////////////////////////////////////////////////仍然移除进度显示文本
                                this.removeEventListener(Event.ENTER_FRAME,enterframeHandler);/////必须移除侦听
                                addChild(new main  );
                                trace("OK");
                }

        }
}

TOP

总结的相当不错,一起学习了!

TOP

同样问题拿出来求助

bitmap,movieClip,可以用以上方法放在第二帧导出.声音用上面的方法不行.
如何实现把声音放在第二帧导出.
http://bbs.actionscript3.cn/thread-8186-1-1.html

TOP

顶楼主,共同学习

TOP

TOP

有好看点的Loading动画不?

TOP

很有用的说
先收藏了!

TOP

有些浏览器包括IE不支持ProgressEvent

这点楼主和蓝色理想都没提到.
用ProgressEvent来侦听下载进度.问题出现在:调试环境下,模似下载可以成功实现.用IE等浏览器打开失败.

loaderInfo.addEventListener(ProgressEvent.PROGRESS,progressHandler);//仍然当进度变化时更新TextField实例的text属性
loaderInfo.addEventListener(Event.COMPLETE,completeHandler);//////////仍然当载入完成后显示内容
function progressHandler(erogressEvent) {
    ttf.text=e.bytesLoaded * 100 / e.bytesTotal.toFixed();
    trace(ttf.text);
}
function completeHandler(e:Event) {
    //其它操作
    loaderInfo.removeEventListener(ProgressEvent.PROGRESS,progressHandler);//仍然当进度变化时更新TextField实例的text属性
    loaderInfo.removeEventListener(Event.COMPLETE,completeHandler);//////////仍然当载入完成后显示内容
   
}

//因为IE不支持,所以我们只能用enterFrame代替它。具体看下面代码

this.addEventListener(Event.ENTER_FRAME,enterFrameHandler);

function enterFrameHandler(e : Event) : void
{
        var percent:Number = this.loaderInfo.bytesLoaded / this.loaderInfo.bytesTotal;
        ttf.text = String(Math.round(percent * 100) + "%");
        if(percent == 1)
        {
                //其它操作
                this.removeEventListener(Event.ENTER_FRAME,enterFrameHandler);
        }
}

TOP

不错,有这么多例子学习了了

TOP

不错,自身的加载在as3里是够烦人的

TOP

这值得长谈的内容~~~

TOP

返回列表