[Egret][文档]显示对象和显示容器(视图)
一、基本概念
视图包括看得见的显示对象和看不见的显示对象容器。
1.显示对象
——图形、文字、视频、图片等。DisplayObject类是所有显示对象的父类。
核心显示类
DisplayObject | 显示对象基类,所有显示对象均继承自此类 |
Bitmap | 位图,用来显示图片 |
Shape | 用来显示矢量图,可以使用其中的方法绘制矢量图形 |
TextField | 文本类 |
BitmapText | 位图文本类 |
DisplayObjectContainer | 显示对象容器接口,所有显示对象容器均实现此接口 |
Sprite | 带有矢量绘制功能的显示容器 |
Stage | 舞台类 |
【注】:显示对象容器类似于div,可以放东西,而Bitmap、Shape这些类似于<img>,只能放对应的显示对象。
【注】:Stage是唯一的、根部容器。Sprite是可以绘制矢量图的容器。
可视属性
——可视属性用来设置可见的对象的一些属性(大小、旋转、透明等等)
- alpha:透明度
- width:宽度
- height:高度
- rotation:旋转角度
- scaleX:横向缩放
- scaleY:纵向缩放
- skewX:横向斜切
- skewY:纵向斜切
- visible:是否可见
- x:X轴坐标值
- y:Y轴坐标值
- anchorOffsetX:对象绝对锚点X
- anchorOffsetY:对象绝对锚点Y
2.显示对象容器
DisplayObjectContainer
封装了一些显示列表中常用的功能:
-
添加、删除子对象
-
访问子对象
-
检测子对象
-
设置叠放次序
3.显示列表
可以把显示列表看成树状结构。
在这个树状结构中,处于最上层的是“舞台”。对应到程序中,是 stage
对象。舞台是Egret显示架构中最根本的显示容器。每个Egret应有且只有一个stage
对象。舞台是这个显示树结构的根节点。
在舞台中,我们还拥有一个主容器。这个容器就是文档类所创建的容器。每一个Egret都会拥有一个文档类,这个文档类必须是一个显示对象容器。
在这个场景中,包含了一个场景背景,背景是由背景图和一颗大树组成的。另外两个元素分别是人物和草地。
二、交换操作
1.本地坐标和舞台坐标
x 和 y 属性始终是指显示对象相对于其父显示对象坐标轴的 (0,0) 坐标的位置,但该位置不一定是舞台的左上角。
若要确定对象相对于全局舞台坐标的位置,可以使用任何显示对象的 globalToLocal() 方法将坐标从全局(相对于舞台)坐标转换为本地(相对于显示对象容器)坐标
//把舞台左上角的坐标(0,0)转换为 container 内部的坐标 var targetPoint: egret.Point = container.globalToLocal(0,0); // 也可以使用localToGlobal() 方法将本地坐标转换为舞台坐标
三、添加、删除显示对象
——在Egret中建立显示对象和渲染显示对象是两个过程。
建立显示对象后,对象会处于内存中,但不会参与渲染过程,只有把显示对象放到显示列表后,显示对象才会参与渲染过程。
如果想将某个显示对象从渲染过程中删除,只需要将其移除显示列表即可。
//创建了一个类型为Sprite的显示对象 var spr:egret.Sprite = new egret.Sprite(); spr.graphics.beginFill( 0x00ff00 ); spr.graphics.drawRect(0, 0, 100, 100); spr.graphics.endFill(); //该对象存在,被添加到显示列表中,在画面中显示 this.addChild( spr ); //该对象存在,但已被移除显示列表,画面上不显示 this.removeChild( spr ); //该对象存在,驻于内存中
1.添加显示对象
this.addChild( spr );
【注】:同一个显示对象无论被代码加入显示列表多少次,在屏幕上只绘制一次。
如果一个显示对象A被添加到了B这个容器中,然后A又被添加到了C容器中。那么在第二次执行 C.addChild(A) 的时候,A自动的从B容器中删除,然后添加到C容器中。
2.删除显示对象
this.removeChild( spr );
【注】:执行删除操作时,“显示对象”必须拥有父级。
可以每次removeChild之前,对即将要被删除的显示对象做一次判断,判断它是否拥有父级:
if( spr.parent ) { spr.parent.removeChild( spr ); }
四、深度管理(层级)
——每一个显示对象在其父级的容器中都拥有一个属于自己的深度值,而且这个值相对于同级显示对象是唯一的。(可以类比为数组下标,中间加一个,则后边都加一,减一个则都减一)
可以通过容器的 numChildren
属性来获取当前容器的子对象数量。
容器.numChildren
1.深度顺序
容器的深度都是从0开始,逐渐累加的。深度大的对象覆盖深度小的对象。
2.添加/删除对象到指定深度
使用的 addChild()
方法会默认按照当前子对象深度进行排序,从0开始,每次深度加1,以此类推。
若要将某一个显示对象添加到一个指定深度的时候,需要使用 addChildAt()
方法。
容器.addChildAt( 显示对象, 深度值 )
可以使用 容器.removeChild( 显示对象 )
将一个显示对象移除显示列表,同样,还可以使用
容器.removeChildAt( 深度值 )
来删除一个指定深度的显示对象。
【注】:移除所有子对象
容器.removeChildren();
3.交换不同深度对象
容器.swapChildren( 显示对象, 显示对象 )
容器.swapChildrenAt( 深度值, 深度值 )
4.重设子对象深度
容器.setChildIndex( 显示对象, 新的深度值 );
五、访问子对象
Egret 提供两种访问容器子对象的方法: getChildAt()
和 getChildByName()
方法。
容器.getChildAt( 深度值 );
容器.getChildByName( 显示对象 )
【注】:通过深度值和 name
属性获取子对象的作用是相同的,但Egret在内部的实现原理却大大不同。
使用深度值获取子对象时,Egret会根据当前容器的显示列表查找指定深度的显示对象,并作为返回值返回给用户。这种检索方式是快速的,不需要进行大量运算。
通过name属性来获取子对象,Egret内部首先会对当前容器的所有子对象进行编译,同时匹配相同的 name
属性值,当发现相同 name
属性的时候,则将该子对象作为返回值返回给用户。虽然在Egret内部进行了相关算法优化,但还是在消耗了一些性能。