利用位图制作高性能加载矩阵型进度条

By Minidxer | February 22, 2009

本文作者:auzn  首发英文版:How to Create a Bitmap(Matrix Graphics) Progress Bar in Flex

通常使用百分比或进度条即可表示处理进度,但有些场合,例如文件分为多个大小相同的块,并对这些块进行处理,这时使用矩阵图形表示文件块的处理是最直观的了.下面我们就来制作这样一个例子.

我们可以先看看程序图片或运行Demo观察(单击切换效果).

clip_image002

Search-256x256 Demo | DownloadDownload Full Project


程序是这样构思的:将单个的小图标封装为类,再由相应的管理类控制这些图标对象,使其在不同状态下转换.

首先准备素材——小图标.

我们可以使用FLASH CS3制作图标.

新建文件KUI.fla,并在库中新建名为”Cel l”的MovieClip.

clip_image004

之后我们在工作区中画好以下图形:

clip_image006

加上高亮:

clip_image008

好了,图标的一个状态出来了,我们可以将其命名为”default”.

再添加影片帧,增加几种状态:

蓝色状态:”start”

clip_image010

绿色状态:”success”

clip_image012

黄色状态:”warning”

clip_image014

红色状态:”error”

clip_image016

防止影片自动播放,我们还要在第一帧加上”stop();”语句.

根据状态名,将每帧写好帧标签:

clip_image018

之后,在库面板中找到Cell影片剪辑,右键导出为SWC文件:

clip_image020

好了,图标的工作结束,我们打开Flex Builder 3,新建KMatrix项目:

clip_image022

完成后,再新建文件夹lib,将之前的Cell.swc移动到lib中:

clip_image024

打开项目的属性面板,点击ActionScript Build Path,切换到Library path,单击Add SWC按钮,在弹出的面板中选择之前在Flash CS3中导出的Cell.swc:

clip_image026

OK后如图:

clip_image028

这样我们就把资源加入到项目中了,接下来进入编程阶段:

建立文件夹com/kingnare/controls,并在controls中新建类MyMatrix:

clip_image030

由MyMatrix类控制其内部的多个Cell对象.

代码如下(查看文件):

package com.kingnare.controls

{

import flash.display.Sprite;

public class MyMatrix extends Sprite

{

private var list:Array;

private var maxWidth:uint;

private var maxHeight:uint;

private var _columnNum:uint;

private var _hDis:uint;

private var _vDis:uint;

public function MyMatrix()

{

super();

_hDis = 1;

_vDis = 1;

_columnNum = 50;

maxWidth = 1;

maxHeight = 1;

}

private function create(num:uint):void

{

if(num < 0) return;

list = [];

for(var i:uint = 0;i<num;i++)

{

var cell:Cell = new Cell();

list.push(cell);

}

updateLayout();

}

private function updateLayout():void

{

var wNum:uint = 0;

var hNum:uint = 0;

var beginX:int = 0;

var beginY:int = 0;

var len:int = list.length;

for(var i:uint = 0;i<len;i++)

{

var cell:Cell = list[i] as Cell;

if(cell)

{

cell.x = beginX+wNum*(cell.width+_hDis);

cell.y = beginY+hNum*(cell.height+_vDis);

if(wNum >= _columnNum-1)

{

wNum = 0;

hNum++;

}

else

{

wNum++;

}

}

}

maxWidth = _columnNum*(list[0].width + _hDis);

maxHeight = (hNum+1)*(list[0].height + _vDis);

drawMatrix();

}

private function drawMatrix():void

{

var i:uint = 0;

while (list && i < list.length)

{

var cell:Cell = list[i] as Cell;

if(!this.contains(cell))

{

addChild(cell);

}

i++;

}

}

public function clear():void

{

while(this.numChildren>0)

{

this.removeChildAt(0);

}

while(list && list.length>0)

{

var cell:Cell = list.pop() as Cell;

cell = null;

}

}

public function set count(value:uint):void

{

if(!isNaN(value))

{

clear();

if(value > 0)

{

create(value);

}

}

}

public function get count():uint

{

return list.length;

}

public function set columnNum(value:uint):void

{

_columnNum = value;

updateLayout();

}

public function get columnNum():uint

{

return _columnNum;

}

public function set hDis(value:uint):void

{

_hDis = value;

updateLayout();

}

public function get hDis():uint

{

return _hDis;

}

public function set vDis(value:uint):void

{

_vDis = value;

updateLayout();

}

public function get vDis():uint

{

return _vDis;

}

}

}

由create方法创建Cell对象并保存到list中,由updateLayout方法布局,drawMatrix方法将Cell对象加到显示列表中.

然后我们在主程序KMatrix中加入测试代码:

package {

import com.kingnare.controls.MyMatrix;

import flash.display.Sprite;

import flash.display.StageAlign;

import flash.display.StageScaleMode;

[SWF(width="700", height="2000", backgroundColor="#333333", framerate="30")]

public class KMatrix extends Sprite

{

public function KMatrix()

{

stage.scaleMode = StageScaleMode.NO_SCALE;

stage.align = StageAlign.TOP_LEFT;

var m:MyMatrix = new MyMatrix();

addChild(m);

m.count = 300;

m.columnNum = 50;

m.x = 50;

m.y = 50;

}

}

}

运行得到结果:

clip_image032

是12行50列,性能很好,CPU占用很低.

将数量加到10000,输出正常,但此时CPU会在一个范围内波动,且数值较之前提高了不少.这是因为大量的Cell对象响应默认事件造成的.下面说说解决的方法,也是本文的重点,利用位图:

不把Cell对象加入到显示列表中,而是将这些Cell对象绘制为一张位图,当某个Cell对象更新状态时,我们再重绘此Cell对象位置对应的位图区..

通过这种方法,可以将之前的成千上万个Cell实例换作一个图位实例来处理.

接下来修改MyMatrix代码:

先声明所需的变量:

private var bitmap:Bitmap;

private var bitmapData:BitmapData;

private var matrix:Matrix;

在构造方法里初始化:

matrix = new Matrix();

bitmapData = new BitmapData(1, 1, true, 0);

bitmap = new Bitmap(bitmapData);

addChild(bitmap);

更新重绘方法,绘制所有的Cell对象:

private function drawMatrix():void

{

bitmapData = new BitmapData(maxWidth, maxHeight, true, 0×00FFFFFF);

var i:uint = 0;

while (list && i < list.length)

{

matrix.tx = list[i].x;

matrix.ty = list[i].y;

bitmapData.draw(list[i], matrix);

i++;

}

bitmap.bitmapData = bitmapData;

}

如何控制Cell对象的状态呢,我们再增加两个方法:

public function setStatus(number:uint, status:String):void

{

if(number < list.length)

{

var child:Cell = list[number] as Cell;

if(child)

{

child.gotoAndStop(status);

matrix.tx = child.x;

matrix.ty = child.y;

bitmapData.draw(child, matrix);

}

}

}

public function getStatus(number:uint):String

{

if(number < list.length)

{

var child:Cell = list[number] as Cell;

if(child)

{

return child.currentFrameLabel;

}

}

return MyMatrix.DEFAULT_FRAME;

}

点此查看完整的MyMatrix类.

OK,现在我们来测试一下吧,修改主程序:

var m:MyMatrix = new MyMatrix();

addChild(m);

m.count = 10000;

m.columnNum = 50;

m.x = 50;

m.y = 50;

m.setStatus(0, MyMatrix.DEFAULT_FRAME);

m.setStatus(1, MyMatrix.START_FRAME);

m.setStatus(2, MyMatrix.SUCCESS_FRAME);

m.setStatus(3, MyMatrix.ERROR_FRAME);

m.setStatus(4, MyMatrix.WARNING_FRAME);

运行结果:

clip_image034

即使在矩阵中快速的移动Mouse,CPU的占用率仍然很低.

我们还可以让它动起来:

点此查看完整的KMatrix类

最后运行结果如图:

clip_image002[1]

这样就可以作为显示某个进程处理进度的图表了.本例中未加入滚动条的支持,这部分功能留给大家了 :)

Topics: Adobe其他 | No Comments » | 1,294 views Tags: , ,

Search Posts