您的位置:首页 > 移动开发 > Objective-C

PIXI.js源码解析(1)——DisplayObject

2017-09-14 17:29 447 查看
Pixi.js是一个用JavaScript写的2D渲染引擎,可以用来在浏览器里做交互图形、动画和游戏等应用,主打支持硬件GPU渲染的WebGL API,如浏览器不支持WebGL,Pixi则会退用HTML5 Canvas来渲染。

接下来先来分析基础显示架构,其实很多渲染引擎都有类似的结构,如果学过as3的估计会感觉特别亲切。

显示架构

DisplayObject是所有可以被渲染在屏幕上的类的基类,DisplayObject继承了EventEmitter。

EventEmitter主要提供一个通用的事件的发送和接受功能,在网上有很多对这个类的解析,自己写一个也很轻松,将直接的函数调用解耦成事件的监听器和事件对象,具体的这里就不详细说了。

DisplayObject的主要属性有

transform

保存了该显示对象的坐标,缩放,旋转,内部使用了很多矩阵运算,所以效率很高,实际上as3也是使用一个transform来保存属性。而我们经常直接调用的x,y属性其实还是从transform里取的,在transform里可以看到,如图




alpha

代表透明度

visible

是否可见

parent

父对象,pixi的显示架构类似一种树结构,每个对象由自己的父对象的引用,而且还有对所以子对象的引用(在container中)

worldAlpha

世界透明度,实际被渲染到屏幕上时的透明度,比如父容器的透明度为0.5,该对象的透明度为0.5,则worldAlpha,最后渲染时的透明度为0.5*0.5=0.25

_filters

所有滤镜对象,pixi支持许多滤镜对象,例如blur模糊滤镜,shadow投影滤镜。

_bounds

边界框,这也是一个非常重要的属性,代表了容纳该对象所需要的一个最小的rect,应该可以翻译为边界框,对象的width和height都是根据该对象得到,以后我们会专门介绍这个类。

_mask

遮罩对象

其他的一些属性估计看英文名就知道什么意思了,这边就不多说了。接下来介绍一下pixi里的广泛运用的一种优化策略。

在pixi.js源码里经常会出现xxxid的属性,例如





这边我们就拿bound举例子吧,计算bound是一个相当耗时的操作,需要递归遍历所有的子级,然后比较,找出极值点,然后找出四个这样的点,组成一个rect。那么一个物体的bound什么时候会改变呢,想一想就可以知道,添加子级,删除子级,改变子级位置时,父级的bound有可能会改变。

例如在container的addchild中



可以看到最后面有一句

this._boundsID++,我们前面已经说到,添加子级,删除子级,改变子级位置时,父级的bound有可能会改变,但是这边却没有立即重新计算bound,而只是递增了_boundsID,有经验的话,应该可以预测到最后在某个地方boundID会与lastboundID进行比较。那么bound到底在什么时候被重新计算呢?

找了一下源码,发现



只有真正需要bound,即调用GetBound时,bound才会比较boundID和lastboundID,如果不一样就重新计算bound。

可以想到,在使用这样一个渲染引擎中,使用一个for添加许多子对象到某容器中是一个相当常见的操作,如果每次addChild都重新计算bound,那估计效率就会很差。

而每次不直接改变bound,而是在可能改变时递增id,然后在对象真正被get的时候,使用id与lastID比较才被重新计算出来,其实是一种非常好的优化方法,一个属性只有他真正的需要的时候才会被计算出来,而不是每次该属性可能改变的时候都重新计算
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息