Actionscript项目中的自加载Preloader最佳实现【转】
这里我要说的是自加载,因为大家都知道flash要实现加载条无非两种方式,用单独的一个专用加载器外部加载,和自加载。由于外部加载这种方式需要编译好的预加载.swf文件,但我们许多项目更需要的是能够随时自定义的Preloader,这样能够在不同的项目中随机应变(类似Flex自带的preloader的实现)
因为要实现自加载,就不得不将侦听ProgressEvent.PROGRESS的代码与项目本身的代码混合在一起,最终只会让项目越来越大,并且如果不经过处理,flash将会加载完所有内容才会运行主程序。做到这一步,这就不得不想到MovieClip边加载边播放的特性,利用这个特性,我们可以实现不需要加载完整个flash就可以运行我们的加载条程序(和早期时间轴上写代码类似)。
package cc.lomo.preloader
{
import flash.display.*;
/**
* 功能:SWF自身的加载条<br/>
* 用法:在需要实现自加载的类声明前加上<code>[Frame(factoryClass="cc.lomo.preloader.Preloader")]</code>
* @author vincent
*/
public class Preloader extends MovieClip
{
/**
* 是否本地运行
*/
protected var mNative:Boolean;
/**
* 模拟当前加载量(本地运行时)
*/
protected var mIndex:int = 0;
/**
* 模拟最大加载量(本地运行时)
*/
protected const mMax:int = 100;
public function Preloader()
{
addEventListener("addedToStage", addedToStageHandler);
}
protected function addedToStageHandler(e:*):void
{
removeEventListener("addedToStage", addedToStageHandler);
//如果已经加载完,那估计就是本地运行了,这时候我们只有搞个假的Preloader了
mNative = loaderInfo.bytesLoaded == loaderInfo.bytesTotal;
addListeners();
}
/**
*
* 侦听加载事件
*/
protected function addListeners():void
{
if(mNative)
addEventListener("enterFrame", enterFrameHandler);
else
{
loaderInfo.addEventListener("progress", progressHandler);
loaderInfo.addEventListener("complete", completeHandler);
}
}
/**
*
* 移除加载事件
*/
protected function removeListeners():void
{
if(mNative)
removeEventListener("enterFrame", enterFrameHandler);
else
{
loaderInfo.removeEventListener("progress", progressHandler);
loaderInfo.removeEventListener("complete", completeHandler);
}
}
/**
* 用ENTER_FRAME模拟加载事件(本地运行时)
* @param e
*
*/
protected function enterFrameHandler(e:*):void
{
mIndex ++;
setProgress(mIndex / mMax);
mIndex > mMax && completeHandler();
}
/**
* 显示进度条
* @param value 进度比 0.0 ~ 1.0
*
*/
protected function setProgress(value:Number):void
{
graphics.clear();
if(value == 1)
return;
graphics.beginFill(0);
graphics.drawRect(0,stage.stageHeight/2, value * stage.stageWidth, 1);
graphics.endFill();
}
/**
* 加载事件
* @param e
*
*/
protected function progressHandler(e:*):void
{
setProgress(loaderInfo.bytesLoaded/loaderInfo.bytesTotal)
}
protected function completeHandler(e:*=null):void
{
removeListeners();
addEventListener("enterFrame", init);
}
/**
* 加载完成后 构造主程序
*/
protected function init(e:*):void
{
//currentLabels[1].name 获得第二帧的标签 也就是主程序的类名以"_"连接如:com_adobe_class_Main,我们需要将其转换为com.adobe.class::Main这样的格式
var prefix:Array = currentLabels[1].name.split("_");
var suffix:String = prefix.pop();
var cName:String = prefix.join(".") + "::" + suffix;
//判断是否存在主程序的类
if(loaderInfo.applicationDomain.hasDefinition(cName))
{
//知道存在主程序的类了,删除enterFrame的侦听
removeEventListener("enterFrame", init);
var cls:Class = loaderInfo.applicationDomain.getDefinition(cName) as Class;
var main:DisplayObject = new cls();
parent.addChild( main );
parent.removeChild(this);
}
}
}
}
再来看看主程序怎么用的:
package
{
import flash.display.Sprite;
import flash.events.Event;
[Frame(factoryClass="cc.lomo.preloader.Preloader")]
public class Test extends Sprite
{
public function Test()
{
super();
this.addEventListener(Event.ADDED_TO_STAGE, onadded);
}
protected function onadded(event:Event):void
{
trace("真实内容加载到舞台");
}
}
}
只需一句代码:
[Frame(factoryClass="cc.lomo.preloader.Preloader")]
这样就实现了加载条,Preloader类是越小越好,所以我没有导入flash.events.Event这个包,还可以压缩的更小,有兴趣的可以研究一下,就是这么简单

浙公网安备 33010602011771号