利用位图制作高性能加载矩阵型进度条
By Minidxer | February 22, 2009
本文作者:auzn 首发英文版:How to Create a Bitmap(Matrix Graphics) Progress Bar in Flex
通常使用百分比或进度条即可表示处理进度,但有些场合,例如文件分为多个大小相同的块,并对这些块进行处理,这时使用矩阵图形表示文件块的处理是最直观的了.下面我们就来制作这样一个例子.
我们可以先看看程序图片或运行Demo观察(单击切换效果).
程序是这样构思的:将单个的小图标封装为类,再由相应的管理类控制这些图标对象,使其在不同状态下转换.
首先准备素材——小图标.
我们可以使用FLASH CS3制作图标.
新建文件KUI.fla,并在库中新建名为”Cel l”的MovieClip.
之后我们在工作区中画好以下图形:
加上高亮:
好了,图标的一个状态出来了,我们可以将其命名为”default”.
再添加影片帧,增加几种状态:
蓝色状态:”start”
绿色状态:”success”
黄色状态:”warning”
红色状态:”error”
防止影片自动播放,我们还要在第一帧加上”stop();”语句.
根据状态名,将每帧写好帧标签:
之后,在库面板中找到Cell影片剪辑,右键导出为SWC文件:
好了,图标的工作结束,我们打开Flex Builder 3,新建KMatrix项目:
完成后,再新建文件夹lib,将之前的Cell.swc移动到lib中:
打开项目的属性面板,点击ActionScript Build Path,切换到Library path,单击Add SWC按钮,在弹出的面板中选择之前在Flash CS3中导出的Cell.swc:
OK后如图:
这样我们就把资源加入到项目中了,接下来进入编程阶段:
建立文件夹com/kingnare/controls,并在controls中新建类MyMatrix:
由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;
}
}
}
运行得到结果:
是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;
}
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);
运行结果:
即使在矩阵中快速的移动Mouse,CPU的占用率仍然很低.
我们还可以让它动起来:
最后运行结果如图:
这样就可以作为显示某个进程处理进度的图表了.本例中未加入滚动条的支持,这部分功能留给大家了
Topics:
Adobe其他 |
No Comments » |
Tags: ProgressBar, 位图, 进度条