Frame metadata tag的本质是编译选项。
通过编译选项
AS3工程 Custom Preloader 動態加載 Application
Adobe Flex 工程的 Application 為2幀的動畫,第1幀為 Pre-load,第2幀為 Application,如果想替換 Adobe Flex 原有的 Pre-loader,那么制作將非常的方便。制作一個新的 preload Component,在 Application 的 preloader 屬性中進行相關的引用就可以完成。
這次討論的不是在 AS3 工程中直接加載 SWF,而是通過 getDefinitionByName(name:String) 的方式對 Application 進行動態加載。
例子是 Unique Instance,詳細請見 Application.as 關于 Instance 的寫法。
- 新建ActionScript工程:PreloaderApp
- 設定Default Application:PreloaderApp.as
- 新建需要動態加載的主工程代碼:Application.as(不用设置为可运行程序)
- 設置工程屬性:Properties->ActionScript Compiler->Additional compiler arguments: -frame start Application(也就是被加载的主程序)
代碼:
PreloaderApp.as
package
{
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.utils.getDefinitionByName;
public class PreloaderApp extends MovieClip
{
/**
* PreloaderApp Constructor.
*/
public function PreloaderApp()
{
this.addEventListener(Event.ADDED_TO_STAGE, handleToStage);
}
/**
* Handle ADDED_TO_STAGE event.
* @param event
*/
private function handleToStage(event:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE, handleToStage);
//stage setting
stage.showDefaultContextMenu = false;
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
createChildren();
addEventListener(Event.ENTER_FRAME, loadApplication);
this.loaderInfo.addEventListener(ProgressEvent.PROGRESS, handleProgress);
this.loaderInfo.addEventListener(Event.COMPLETE, handleComplete);
}
private var _preLoadingText:TextField;
/**
* createChildren
*/
private function createChildren():void
{
_preLoadingText = new TextField();
_preLoadingText.text = "Loading...";
_preLoadingText.textColor = 0x000000;
_preLoadingText.x = (stage.stageWidth / 2) - (_preLoadingText.width / 2);
_preLoadingText.y = (stage.stageHeight / 2) - (_preLoadingText.height / 2);
_preLoadingText.autoSize = TextFieldAutoSize.CENTER;
addChild(_preLoadingText);
}
/**
* Handle progress.
* @param event
*/
private function handleProgress(event:ProgressEvent):void
{
var percent:int = Math.floor(event.bytesLoaded / event.bytesTotal * 100);
_preLoadingText.text = "Loading..." + percent + "%";
}
/**
* Handle load complete.
* @param event
*/
private function handleComplete(event:Event):void
{
this.loaderInfo.removeEventListener(ProgressEvent.PROGRESS, handleProgress);
this.loaderInfo.removeEventListener(Event.COMPLETE, handleComplete);
}
/**
* Load main application.
* @param e
*/
private function loadApplication(event:Event):void
{
if (currentFrame == totalFrames)
{
removeEventListener(Event.ENTER_FRAME, loadApplication);
stop();
var cls:Class = getDefinitionByName("Application") as Class;
addChild(new cls() as DisplayObject);
removeChild(_preLoadingText);
_preLoadingText = null;
}
}
}
}
Application.as
package
{
import flash.display.Sprite;
import flash.events.Event;
public class Application extends Sprite
{
private static var _instance:Application;
/**
* Unique instance.
* @return
*/
public static function getInstance():Application
{
return _instance;
}
/**
* Application Constructor.
*/
public function Application()
{
super();
addEventListener(Event.ADDED_TO_STAGE, initOnStage);
}
/**
* Handle ADDED_TO_STAGE event.
* @param event
*/
protected function initOnStage(event:Event):void
{
//remove ADDED_TO_STAGE listener.
this.removeEventListener(Event.ADDED_TO_STAGE, initOnStage);
//Set unique instance.
if (!_instance)
_instance = this;
//...
}
}
}
通过Frame metadata tag
神奇的 Frame metadata tag - 用它做AS3 preloader
上一篇blog 的翻译了怎么用[Frame]做程序的模块化, 让我们再看那篇经典文章后, 大牛 keith 又是怎么用[Frame]实现了AS3的preloader: 原文章 Preloaders in AS3, 时间: Jan 21, 2007. 下面是概要性的翻译:
大家知道, flex程序是典型的2侦模型程序, preloader是在第一侦, 主程序在第二侦.
keith同学用[Frame]标签,主要是解决了让程序有2侦,并且让自定义的AS3 preloader类在第一侦.
直接在代码中分析吧,首先看主应用程序类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
package
{
import
flash.display.Sprite;
import
flash.display.Bitmap;
//在主程序类中加入frame meta, MyPreloader 类就是一个简单的自定义的preloader类
[Frame(factoryClass=
"com.bit101.MyPreloader"
)]
public
class
Main
extends
Sprite
{
//为了体现preloader的价值, 故意选一个很大的图片文件,
//这个主程序主要就是加载显示这个大图片
[Embed(source=
"big_asset.jpg"
)]
private
var
Asset:Class;
public
function
Main()
{
init();
}
public
function
init():
void
{
var
asset:Bitmap =
new
Asset();
addChild(asset);
}
}
}
|
下面是 MyPreloader 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
package
com.bit101
{
import
flash.display.DisplayObject;
import
flash.display.MovieClip;
import
flash.display.StageAlign;
import
flash.display.StageScaleMode;
import
flash.events.Event;
import
flash.utils.getDefinitionByName;
//注意, 是继承自MovieClip而不是Sprite, 因为处理和侦相关
public
class
MyPreloader
extends
MovieClip
{
public
function
MyPreloader()
{
stop();
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
public
function
onEnterFrame(event:Event):
void
{
graphics.clear();
if
(framesLoaded == totalFrames)
{
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
nextFrame();
init();
}
else
{
var
percent:
Number
= root.loaderInfo.bytesLoaded / root.loaderInfo.bytesTotal;
graphics.beginFill(
0
);
graphics.drawRect(
0
, stage.stageHeight /
2
–
10
,
stage.stageWidth * percent,
20
);
graphics.endFill();
}
}
private
function
init():
void
{
//这里全部用的是反射机制, 没有直接用Main类,
//这是避免直接import Main类, 这将引起Main以及它引用的类加入到了MyPreloader
var
mainClass:Class = Class(getDefinitionByName(“Main”));
if
(mainClass)
{
//此处不能直接调用main的构造函数, 因为那样会涉及到stage, 而stage在被add as child之前还是空
var
app:
Object
=
new
mainClass();
//主程序对象是作为 MyPreloader 的子对象, 而不是根的子对象
//这一点和flex preloader不一样
addChild(app
as
DisplayObject);
}
}
}
}
|
两者区别
设前置载入帧为Preloader.as,被载入的主程序为Main.as第一种通过编译选项
项目设置的可运行程序是Preloader。
Main不用设置可运行。
编译选项指定的是被加载的Main。
AS3 模块 优化不可优化模块。
外部一个swf通过Loader载入Preloader.swf后,可以通过loader.contentLoaderInfo.applicationDomain.getDefinition("Main")获得Main类。
可以获得Preloader类。
第二种通过Frame tag的
项目设置的可运行程序是Main。
Preloader不用设置为可运行程序。
Frame tag加在Main上。
AS3 模块 优化可以优化模块。因为模块指明的优化的可运行程序是 加载他 的主程序。
外部一个swf通过Loader载入Main.swf后,不可以通过loader.contentLoaderInfo.applicationDomain.getDefinition("Main")获得Main类。
可以获得Preloader类。估计只能通过Preloader内初始化Main类了。