MatrixTurn源码阅读

在看cacheAsBitmap 相关资料时,找到bit101的一篇文章,http://www.bytearray.org/?p=290 全文如下:

One of the feature I would really love to see in a future release of the Flash Player is a native rasterizer for display objects. Imagine something like :

myMovieClip.rasterize = true;

This code would rasterize your DisplayObject as an animated PNG. It would bring crazy improvements for designers and coders who want to improve the rendering performance of any animation. This would be in fact the same behavior as the Banana Slice component I talked about.

When talking about this, some people could think "Well, you have cacheAsBitmap for that". The reason why such a feature would rock is mainly due to the fact that cacheAsBitmap is very dangerous. Well, it won't hurt you :) , but it can definitely hurt your application performance.

As I said before, when cacheAsBitmap is set, the DisplayObject is cached as a bitmap on memory and the Flash Player is using this copy to render it on screen. The main problem that we have here is that if you do more than moving this DisplayObject on x and y, for each frame the Flash Player is updating the cached copy on memory before updating the screen. So if you apply any rotation, scale, alpha, or even if you have any key frames in your DisplayObject you will get performance decrease.

Hopefully, you can bypass this limitation by creating a BitmapData by yourself, draw the MovieClip on it, and pass it to multipe Bitmap instances. So let's take a simple example, in the folllowing movie, when you click on the "cacheAsBitmap" button, I create multiple instances of an Apple MovieClip, set cacheAsBitmap, and move them on screen :

var apple:Apple;

for (var i:int = 0; i< 100; i++)
{
apple = new Apple();

apple.cacheAsBitmap = true;

addChild ( apple );
}

When you click on the "draw" button, I first create an instance of the apple MovieClip, draw it on a BitmapData and then create Bitmap instances linked to the one and unique BitmapData instance :

var source:AppleSource = new AppleSource();

var buffer:BitmapData = new BitmapData ( source.width, source.height, true );

buffer.draw ( source );

var bitmapApple:BitmapApple;

for (var i:int = 0; i< 100; i++ )
{
bitmapApple = new BitmapApple( buffer );

addChild ( bitmapApple );
}

很不错的一篇文章,文章中又提到了Banana Slice,地址http://www.bytearray.org/?p=117

文章是建议adobe对movieclip做一些优化操作。在这篇文章的评论里,有人提到了MatrixTurn,就是这篇博客的重点了。

代码虽然不多,但写的实在复杂,花了整整一天才看懂大概。写了一些简单的笔记:

aGroupName
下标是自增的index
值是groupName

aGroup
下标是每个groupName所对应的index
值是 一个array
在这个array中,每一个元素又是一个array对象,代表state相关信息
即是和aGroupState是对应的
自array的信息如下:
0 = new Array
1 =

在0下标表示的array中,
其信息又是如下:
2 = sSnap
3 = bSmooth
9 = layer
5 = nBorder //这个位置和state貌似不对应
4 = totalFrames

aGroupValue
下标是每个groupName所对应的index
值是 一个array
在这个array中,
0 = convert 表示convert操作是否开始,这个是在convertGroup方法中被修改的,如果开始了那么再调用addState就会报错
1 = _bSmooth
2 = _sSnap
3 = new Array,存储这个groupName下的所有实例,这个是在convertGroup方法中被修改的
4 = _colorTransform
5 = _fctBitmapDataTransformation
6 = _bAutoFirstFrameConvert
9 = _nLayers
10 = _fctMovieClipTransformation
11 = 0 这个是在convertGroup方法中赋值的,代表已经完成initialisation的实例数,也是在convertGroup中修改的
即是这个array存放是groupName对应的mc在转换时的一些参数!!!

aGroupState
下标是每个groupName所对应的index
值是 一个array
在这个array中,每一个元素又是一个array对象代表一个state信息
即是说,每个groupName会对应多个state,这些state组合成一个array存在aGroupState中
每一个state信息又是通过array来表示的,具体如下:
0 = _state; 状态名
1 = _bSmooth;
2 = _sSnap;
3 = _nBorder;
4 = _colorTransform;
5 = _fctBitmapDataTransformation;
9 = _nLayers;
10 = _fctMovieClipTransformation;
7 = nLastState 这个是在linkState方法中赋值的
8 = _sFunction 这个是在addLoadState方法中赋值的

aTaskList
下标是每个groupName所对应的index
值是 一个array
在这个array中,
0 = _mcRef;对应的movieclip
1 = nId; groupName所对应的index
2 = new Array; groupName下的实例 在convertGroup中改变

aTaskListId
下标是自增的index
值是groupName所对应的index
表示即将要被convert的group

aWaitingListId
下标是自增的index
值是groupName所对应的index
表示在等待中的group

aTaskComplete

aGroupComplete

每次createGroup之后,nGroupId就表示新插入的group
这个时候,一般都是调用addState addLoadState方法,对这个group做补充操作
addState addLoadState会用nGroupId做验证,
换句话说,createGroup一定要遭addState addLoadState之前调用!
同理,addLoadState也最好是在addState之后调用,因为它可能也会用到lastState

每一个group至少需要一个state
不然convertGroup方法报错

state其实就是movieclip中的帧label

这个开源项目,核心思想就是把一个 movieclip转换成bitmap,它还支持movieclip的scale rotation 等操作。

还有一个亮点是,movieclip到bitmap的转换过程是分散到多帧中进行的,这样避免某一帧的执行时间过长。

再每次draw之后都判断本回合操作时间,如果超过指定的时间就暂定draw操作。

但之后是怎么再次启动的,我没有看懂,惭愧一下~

还有一点不太理解的是,在bitmap切换过程中,都是通过removechild addchild来实现的,为什么不直接更换bitmapdata属性的?

是因为要支持不同的effect吗?

另外,项目中也用到了Event.FRAME_CONSTRUCTED,之前没碰到过,所以查了下资料,

可以参考这篇文章http://hi.baidu.com/hihuanshi/item/fefc976e6a53650aa0cf0f6a

全文摘录如下:

做flash IDE 项目时,碰到了一种令我难以理解的事情,假设在舞台上有个影片剪辑mc,mc含有多帧,假设第二帧上事先放有显示对象childrenA,在舞台我写代码如下:

mc.gotoAndStop(2);

mc.childrenA.visible=false; 

   问题出现了,flash竟然给我报访问空对象的错误,但查实“childrenA”对象是好好滴待在那的,trace(mc.numChildren)有是和帧上对象数吻合的,难道说这两句代码不能同步进行?抱着怀疑的心态,经测试n次得出结果,现分享:

      分析:MovieClip的帧显示对象的构造和帧代码是异步执行,所以才造成在第二帧代码访问帧上的对象为null的情况。 注:如果帧上对象都是小东西的话,可能就不报此错误了。 

    解决方案:

mc.gotoAndStop(2); 

mc.addEventListener(Event.FRAME_CONSTRUCTED, onFRAME_CONSTRUCTED);   

function onFRAME_CONSTRUCTED(e:Event):void  

{
     
    if (mc.getChildAt(mc.numChildren - 1) == null) {

         return;

    } 

   mc.removeEventListener(Event.FRAME_CONSTRUCTED, onFRAME_CONSTRUCTED);

   mc.childrenA.visible=false  

}

        关于FRAME_CONSTRUCTED的解释:在帧显示对象的构造函数运行之后但在帧脚本运行之前调度。如果播放头不移动,或者只
有一帧,则会继续以帧速率调度此事件。此事件为广播事件,这意味着具有注册了此事件的侦听器的所有显示对象都会调度此事
件。
通俗点解释:就是添加一个对象完成后就派发一下这个事件,我监听最后一个显示对象不为null的话,程序就可以顺利进行了……

可以参考http://help.adobe.com/zh_CN/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html#event:frameConstructed

原文地址:https://www.cnblogs.com/tianlanliao/p/3498211.html