AS3中的DisplayObject有一个render事件,他会在重绘DisplayList之前触发,这给我们提供了在重绘之前最后一次操作的机会。每次需要DisplayObject触发render事件时,都要调用一次 stage.invalidate();
下面用一个小例子来说明一下具体用法吧。
假设我们现在要写一个list组件,该组件有addItem()方法用于添加list项目,和remvoeItem() 方法用于删除list项目,当然还可能有addItemAt(),removeItemAt()等方法,这些方法调用后,都需要对list内的显示对象进行重新排列。
我们先实现一个List类,用于显示列表项目List类中,有addItem() 和 removeItem() 这两个方法提供给外部调用,用于添加和删除list项目,这两个方法中除了将列表项目添加/删除,还要调用一个方法来重新对list中的项目进行排列,layoutContents()。关键就是,这个layoutContents()的调用,他的调用次数越少,那效率当然就越高啦,如果是常规的做法,就是类似这样:
代码:
public function addItem ( item : DisplayObject ) : void {
addChild ( item ) ;
layoutContents () ;
}
将item加入后,重新排列列表
下面是List类的源代码:
代码:
package {
import flash . display . DisplayObject ;
import flash . display . Sprite ;
import flash . events . Event ;
public class List extends Sprite {
public function addItem ( item : DisplayObject ) : void {
addChild ( item ) ;
layoutContents () ;
}
public function removeItem ( item : DisplayObject ) : void {
if ( contains ( item )) {
removeChild ( item ) ;
layoutContents () ;
}
}
//对内部项目进行排列,可以是任意的排列算法
protected function layoutcontents () : void {
trace ( " do layout " ) ;
var y : Number = 0 ;
var num : int = numChildren ;
for ( var i : int = 0 ; i < num ; i ++ ) {
var child : DisplayObject = getChildAt ( i ) ;
child . x = 0 ;
child . y = y ;
y += child . height + 2 ;
}
}
}
这个程序粗看似乎没什么问题,但却存在一个效率问题,如果只调用一次addItem,没问题,如果调用10次呢? 前9次的layoutcontents()都不是必须的,只有第十次才是真正需要的这样程序的效率就降低了。
我们可以试一下,先需要一个简单的ListItem
代码:
package {
import flash . display . Shape ;
public class ListItem extends Shape {
public function ListItem () {
super () ;
graphics . beginFill ( 0 xFF6600 ) ;
graphics . drawRect ( 0 , 0 , 30 , 16 ) ;
graphics . endFill () ;
}
}
}
然后测试
代码:
package {
import flash . display . Sprite ;
public class ListTest extends Sprite {
public function ListTest () {
var list : List = new List () ;
addChild ( list ) ;
list . addItem ( new ListItem ()) ;
list . addItem ( new ListItem ()) ;
list . addItem ( new ListItem ()) ;
}
}
}
我们可以看到,输出了3次 do layout 说明layoutcontents执行了3次,前两次都是多余的。现在,解决办法就是利用render事件啦。因为当前帧内,显示列表更新前会触发render事件,所以在render事件触发后来排列列表项目,就可以保证排列方法在做了任意次的添加或删除操作后只需调用一次,从而提高效率。
这么做只需要对List类稍做一些改动,首先肯定是要监听render事件,我们可以仅监听stage对象的render事件即可,因为这样以后可以做一个独立的RepaintManger来管理所有组件的重绘(可以参考AsWing的RepaintManager类)。
在render事件触发后,做我们需要的调整,由于要render事件触发,就必须先调用stage.invalidate() ,所以每次添加或删除list项目后,都要执行一次该方法,即:
代码:
public function addItem(item:DisplayObject):voide { ...... stage.invalidate() } 由于是监听的stage的render事件, 所以在添加删除操作后,要做一个标记,表示list有改动,需要在render事件后重新排列,如果该标记为false,那么即使render触发了也不 做排列,因为stage的render事件也有可能是由于该stage内的其他child需要重绘而造成stage的render触发。
下面是改过后的List代码
package {
import flash . display . DisplayObject ;
import flash . display . Sprite ;
import flash . events . Event ;
public class List extends Sprite {
private var changed : Boolean ;
public function List () {
super () ;
addEventListener ( Event . ADDED_TO_STAGE , __addToStage ) ;
}
public function addItem ( item : DisplayObject ) : void {
addChild ( item ) ;
requireLayout () ;
}
public function removeItem ( item : DisplayObject ) : void {
if ( contains ( item )) {
removeChild ( item ) ;
requireLayout () ;
}
}
private function requireLayout () : void {
changed = true ;
if ( stage != null ) stage . invalidate () ;
}
//对内部项目进行排列,可以是任意的排列算法
protected function layoutContents () : void {
trace ( " do layout " ) ;
var y : Number = 0 ;
var num : int = numChildren ;
for ( var i : int = 0 ; i < num ; i ++ ) {
var child : DisplayObject = getChildAt ( i ) ;
child . x = 0 ;
child . y = y ;
y += child . height + 2 ;
}
}
private function __addToStage ( e : Event ) : void {
stage . addEventListener ( Event . RENDER , __render ) ;
if ( changed ) stage . invalidate () ;
}
private function __render ( e : Event ) : void {
if ( changed ) {
layoutContents () ;
changed = false ;
}
}
}
}
当我们再次运行ListTest的时候,do layout 只输出了一次。就是这些内容,当然,你可能会说,需要做到这些根本不需要这么复杂,只要公开layoutContents方法,在所有操作调用之后让调用者自行调用一次layoutContents()。
在这个例子中当然可以,但是当情况很复杂的时候,使用者每进行一次操作都要自行调用更新的方法,这样做并不是好的解决方案。试想,如果 flashplayer不会为我们处理显示DisplayObject的工作,而是每次addChild/removeChild之后,我们都需要自行调 用flashplayer底层的方法来让我们需要的东西显示出来,这样做显然很不好。
分享到:
相关推荐
Unity Render Streaming相关的webserver服务运行文件
Render-and-Compare loss that allows 3D shape and pose to be learned with 2D supervision. We evaluate our method on the challenging real-world datasets of Pascal3D+ and KITTI, where we achieve state-of...
3D-render.zip,一个简单的web服务,它使用自定义文本呈现搅拌机3d场景。,3D建模使用专门的软件来创建物理对象的数字模型。它是3D计算机图形的一个方面,用于视频游戏,3D打印和VR,以及其他应用程序。
Render Monkey安装程序 共5个分卷,3/5
一键将角色的Animator或Animation去掉,将SkinnedMeshRender更换为一般的Mesh Render,完成将动画效果的实现从CPU转移到GPU运算的目的,来利用GPU Instancing技术减少Draw Call。 • Convert assets quickly and ...
D3D11_Render
安装好原程序,了世哪个汉化文件《Renderin》放到C:\Program Files\Google\Google SketchUp 8\Plugins\Renderin目录下替换原文件,打开SU8在插件下Renderin菜单点License,在弹出的窗口输入号码,点Apply等一会在...
Offline Render is an easy to use, realtime capture plugin for Unity. It allows you to capture the game view to a multi-channel OpenEXR or multiple PNG files, supporting not just the final output image...
JsRender.zip(jsrender.js和jsrender.min.js合集)
This software is TextCanvas by katahiromz. It can render shapes as a string.
3D-PG3Render.zip,我基于物理的cpu pet渲染器,3D建模使用专门的软件来创建物理对象的数字模型。它是3D计算机图形的一个方面,用于视频游戏,3D打印和VR,以及其他应用程序。
jsrender.js , jsrender.min.js下载
render to html
为您列举一些renderDoc方面的下载的内容,renderdoc教程、render doc安装、renderdoc plugin等资源。把最新最全的renderDoc推荐给您,让您轻松找到相关应用信息,并提供renderDoc下载等功能。本站致力于为用户提供更好...
使用fbo来实现render to texture演示
render函数 vue通过 template 来创建你的 HTML。但是,在特殊情况下,这种写死的模式无法满足需求,必须需要js的编程能力。此时,需要用render来创建HTML。 render方法的实质就是生成template模板; 通过调用一...
FINAL_RENDER_R3.5_SE_SP3_FOR_3DSMAX_2012_WIN64
3DS_read_render_class 3DS_read_render_class
richfaces标签render的使用
主要介绍了element-ui table组件如何使用render属性的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧