当前位置:文档之家› ch20

ch20

第20章 ActionScript 3视觉编程精要

ActionScript 3视觉编程(Display Programming)的内容是关于如何使用ActionScript 3来生成和控制各种图形、动画、视频等可视元素。这些可视元素通常在Flash Player的舞台上显示。这些可视元素又称为显示对象(Display Object)。

视觉编程可以说是Flash的发家之本,也是ActionScript 早期版本最关注的方面。ActionScript 3不但继承了其先辈们的优点,还对视觉显示做了更加透彻的分析、抽象和设计,进行了大刀阔斧的革新。现在的ActionScript 3视觉编程架构更加标准、更加规范、更加易于理解和掌握。当笔者赏析了ActionScript 3 的所有显示对象类型和其整体构架后,都感到非常满意。可以看出,这次整体的架构设计是经过深思熟虑和花了大力气的。ActionScript 3视觉编程架构与其他语言相比有自己强烈的特色,也是对Flash贴身定做的结果。

本章导读

本章从ActionScript 3视觉显示架构和面向对象设计思想两个角度,讲述了相关的重要概念和类库架构。建议所有读者通读本章。

对于初学者来说,20.3.4节可以跳过不看。

20.1 什么是显示对象

Display Object,本书意译为“显示对象”1。其准确含义是可以在舞台上显示的对象。可以显示的对象,既包括可以直接看见的图形、文字、视频、图片等,也包括不能看见但却真实存在的显示对象容器(Display Object Container)。

从ActionScript 3的角度来看,不管多复杂的视觉图形都是由显示对象和显示对象容器组合而成的。

那么它们是如何组合而成的呢?请看下面的Flash例子。在这个Flash例子中,有一块黑板,黑板上有几个字,黑板前面放着一盒粉笔和一只单独拿出来的粉笔。如图20-1所示。

1 Display Object,又译为“可视对象”、“视觉对象”、“可视元素”等。本书遵从官方中文文档译法,直译为“显示对象”。但笔者以为,使用“可视对象”或“视觉元件”为佳,这样读者比较容易理解。在本书中,英文Display Object和显示对象意思一样。

·328·

图 20-1 显示对象示例

中包含着一些显而易见的逻辑。比如,当我们移动黑板时,自然希望黑板上

管理子对象的方法。父容器可以通过getChild()、getChildAt()等方法访问到每一个子对象,每一个子对象都可以通过parent属性访问到父容器。所以,ActionScript 3的显示对象结构又是一个双向的树图。

图20-2就是“图 20-1 显示对象示例”中SWF文件的可视内容解构图——一个标准的显示对象等级结构图。

flash

ActionScript 3第

20章 ActionScript 3视觉编程精要

·329·

图20-2 显示对象等级结构图

由图20-2就可以将这个复杂视图的等级结构看清楚了。

首先,在这个等级架构的最上层,就是舞台(Stage )。舞台是最根本的容器,包含着当前SWF 所有的显示对象。舞台又是一种特殊的容器,每个Flash 应用程序只能有一个舞台容器。如图20-2所示,舞台也是整个对象树结构的根节点。

其次,在舞台下面的也是一个容器,被称为当前SWF 主类的实例。这是什么意思呢?在ActionScript 3中,每个SWF 都和一个ActionScript 3 类相关联。这个类就称为SWF 的主类。当这个SWF 设定了文档类(Document Class ),那么文档类就成了主类;如果是由Flash CS3生成的且没有指定文档类,那么默认的MainTimeline 类就是主类。关于这些,会在第23章“Flash CS3:库元件的类绑定”中详细阐述。此处读者有个模糊概念即可。

与ActionScript 2、ActionScript 1对比

与ActionScript 2不同的是,ActionScript 3中的root 指向的是当前SWF 主类的实

例。详细能见第23章“Flash CS3:库元件的类绑定与stage 、文档类”。

然后,才到了Flash 的内容部分。可以看出,这Flash 中的内容无非由两个容器和一个显示对象组成。每个容器中又有自己的显示对象或者容器。图20-2中,树枝都是容器,树枝的末端都是非容器对象,比如:位图、文本框等。 20.1.2 显示列表:显示对象模型

图20-2

“显示对象等级结构图”中揭示了ActionScript 3显示对象模型的一般结构,是一个树状图结构。用树状图的方式列出一张清单,上面有所有的显示对象和容器,那么这张清单就称为显示列表(Display List )。

·330· 整个树状图就是显示列表(Display List )的图形表现。显示列表是ActionScript 3中的新概念。显示列表就是一张清单,只有清单上列出的内容才会在舞台上显示出来。换句话说,Flash 只渲染显示列表中存在的内容。我们看到每个容器和其子对象又可以看成一个局部树状图。因此,也可以说每个容器拥有自己的列表,包含着自己的子对象和子容器。

一个程序中的显示对象也分为在显示列表中(on-list )的对象和不在显示列表中(off-list)的对象两种:在显示列表中的显示对象会被渲染而出现在舞台上;不在显示列表中的显示对象依然存在,只是不被渲染呈现而已。这儿的显示列表指的是完整的显示列表,即从Stage (舞台)开始的列表,而不是容器的局部列表。

所以,在ActionScript 3中新创建一个显示对象,不会马上在舞台上显示出来,必须要加入到显示列表中,Flash Player 才会渲染和显示它。加入列表的方法就是我们所熟悉的addChild()或addChildAt()方法。

了解了显示对象模型后,我们最迫切要知道的莫过于哪些具体的对象是容器,哪些具体的对象是非容器对象。下面,来看看ActionScript 3中显示对象的种类。

20.2 ActionScript 3中显示对象的种类

ActionScript 3的显示对象架构乍一看很复杂,不算上UIComponent 的子类,就有7到8层之多,共有20多个莫名其妙的类。看起来很头疼!但实际上,它的设计是非常的简洁优雅,远远比 ActionScript 2代一个MovieClip 打天下强多了。只要真正弄清了它的设计思路,就可以高屋建瓴、一览无余了。这个架构逻辑清晰,非常易懂易记。所以,先抛开ActionScript 3 的帮助文件,我们一起来看看为什么要设计这样一个架构,搞出20多个怪胎出来。

先从ActionScript 2中我们非常熟悉的MovieClip 说起。

20.2.1 ActionScript 2中的MovieClip

先来追忆一下ActionScript 2中无所不能的先贤:MovieClip (影片剪辑)。这位兄台无所不能:既可在其中画矢量图,又可在其中贴位图;可在其中做影片,也可嵌套子影片;偶尔用来加载,闲来客串按钮;三教九流皆可放,肚皮天下第一广。它的父类何人,原来是元始天尊Object 类。

这样的设计看起来似乎很爽,因为大大节约了脑细胞。所以在ActionScript 2中,MovieClip 类公开的属性和方法共有100多个!还可直接继承根类!任何一个有过大型OOP 项目经验的老手,都会毫不犹豫地指出,这样的架构设计是失败和混乱的,代价是巨大的。

功能大杂烩带来了MovieClip 的滥用。首当其冲,其第一弱点就是系统资源的浪费。举个例子, 我新建一个空MovieClip 实例A ,只是想让它做个容器,以便在其中放几个有内容的子影片剪辑。这样我操作A 的位置和渐变时,子影片剪辑会统一变化。这种情况是ActionScript 2编程中常常遇到的。可就是这么一个简单的纯容器A ,ActionScript 2&1都会毫不犹豫的把MovieClip 所有的属性和方法都塞给A 。谁让A 是Movie Clip 类的实例呢?可在这种简单

flash

ActionScript 3第20章 ActionScript 3视觉编程精要

·331·应用下,我们要A 的其他 90多个功能干什么呢?而且还不算最耗资源的对Timeline (时间轴)的支持!我们每天都在用代码创建影片剪辑,但创建的影片剪辑有多少用到了MovieClip 大多数的功能和Timeline (时间轴)?事实上,只有一部分通过Flash 创建的MovieClip 才需要时间轴的支持。这样的浪费值得吗?

批评之后,必须理性地说,这样的错误是有其历史局限性的,我们不能苛求前人。在经过了这么多年发展之后,ActionScript 3 语言设计师对Flash 视觉架构有了更深更透彻的理解。看现在的显示对象架构,那真是清爽自然。这体现在ActionScript 3语言设计师对整个Flash 视觉系统的抽象上。他们抽象和解构的功力很深!让笔者深深佩服!整个显示对象架构中各个抽象类和子类的设计划分清楚、职责清晰、稳健高效、堪称优雅!笔者在看.Net FrameWork 的System.Drawing 架构设计时都没有这个感觉。毕竟Flash 是靠视觉起家的,与视觉动画交互打交道最深。

下面简要说一下ActionScript 2中MovieClip 的如此多的功能是如何被清晰划分到ActionScript 3中的。首先,与屏幕显示相关的属性和行为被归纳到了最顶层的抽象类DisplayObject 中;其次,MovieClip 作为容器的属性和行为(如创建子剪辑、深度管理等)被归纳到了抽象类DisplayObjectContainer 类中;MovieClip 中加载资源的相关部分被划分给了单独的Loader 类对象来完成;MovieClip 绘制矢量图部分API 则被划分给专门的Graphics 类对象。只有MovieClip 特有的帧控制(如gotoAndStop 等),才被划分给ActionScript 3中的MovieClip 类对象。由此可见,MovieClip 在ActionScript 3中的应用和地位都大大不如从前重要,被各有分工明晰、功能更加强大的类代劳。Sprite 类将代替MovieClip 类成为我们在代码开发中最常用到的容器类。

下面,我们来详细领略ActionScript 3中显示对象清晰的设计原则和优雅的系统架构。 20.2.2 ActionScript 3 显示对象种类划分:一个统一、两个层次

一个统一是指,所有的显示对象都统一于DisplayObject 类。所有的显示对象(包括容器)都是其子类的实例。不再像ActionScript 2中位图、文本、MovieClip 那样直接继承根类Object 而各自割据。

第一大层次:是否可以接受互动事件?可以接受的,称为可互动的显示对象(Interactive Object );不可接受的,称为非互动显示对象。所谓接受互动事件,是指能够接受鼠标单击、键盘敲击等人机交互事件。单纯的矢量图形、位图、视频都是不能接受这些事件的,那么就归于非互动显示对象这一类。如按钮、MovieClip 、UI 组件、文本框等可以接受的,就归为可互动 的显示对象。

第二大层次:是否可以容纳其他显示对象?意思就是,可否将其他显示对象纳为自己的子对象。可以容纳其他显示对象的,称为显示对象容器(Display Object Container );不可容纳其他显示对象的,称为非容器显示对象。

·332

· 20.3 *显示对象类库架构

读者可以参见“图10-1抽象类:理想的继承架构”,以加深对显示对象类架构的理解。 20.3.1 InteractiveObject 类和非InteractiveObject 类

DisplayObject 类下面一层的抽象很精彩,即第一大层次。架构设计师的原意是将所有视觉元件分为两大类:可以接受人机交互事件的和不可以接受人机交互事件的。所以就有了InteractiveObject 类和非InteractiveObject 类之分。

flash

ActionScript 3第20章 ActionScript 3视觉编程精要

·333·由于非InteractiveObject 的几个类之间差别太大,也抽象不出什么共同点,所以,干脆就分成了InteractiveObject 的6个同级兄弟 AVM1Movie 、Bitmap 、MorphShape 、Shape 、StaticText 和Video 。在这几个子类中,又分为可以用代码创建的和不能通过代码接触的。

不可以用代码接触的只有两个种对象:StaticText 和MorphShap 类的对象。所谓不可以代码接触的,是指只能通过Flash 创作工具来创建或改变的对象。StaticText 类对象是静态文本框,只可以在Flash CS3中用文本工具创建。另外一个是MorphShape 类对象,这种对象是在Flash 中创建形状渐变时自动生成的。

剩下的几个都是可以用代码创建的:Bitmap (位图对象)可以通过BitmapData 对象来创建,也可以从外部载入。Shape (形状)是专门用来绘制矢量图的。Video (视频对象)是专门用来播放视频的,可以来自文件也可以来自网络流媒体。

下面要说到的是AVM1Movie 。所谓AVM1Movie ,意思就是说Actionscript Virtual Machine 1(ActionScript 虚拟机1)所支持的SWF 影片,也就是ActionScript 1和ActionScript 2的影片。由于ActionScript 3 采用的是A VM2,所以和A VM1影片无法跨脚本交流,文件格式也有诸多不同。因此,必须要把它同A VM2 SWF 影片区分开来,所以产生了这个类。一旦我们加载一个A VM1影片到A VM2 的SWF 中时,Flash Player 会自动创建一个AVM1Movie 的实例来包装这个SWF 。

20.3.2 容器类和非容器类

到了InteractiveObject 下一层了,即第二大层次,这一层共有3个类。这一层使用了容器和非容器的概念来区分可视对象类。所谓容器,就是可以在其中加载其他的 DisplayObject 子类对象。所谓非容器,就是说不能在它里面加入其他的DisplayObject 。“容器”,这个性质实在太重要了,而在这一层中这样抽象出来实在很高明、很到位。

先讲讲非容器的两个类,TextField 和SimpleButton 。 TextField ,就是熟悉的动态文本框,这里暂不细说。下面来说说SimpleButton (简单按钮),这个名字虽然和我们在ActionScript 2中碰到的SimpleButton 一样,但实际上二者有很大的差别。ActionScript 3中是Flash API , ActionScript 2中是UIComponent 组件,有着本质的不同。

剩下的就是DisplayObjectContainer (显示对象容器)类了。可以在DisplayObjectContainer 的子类对象中添加其他显示对象。但要注意一点,DisplayObjectContainer 本身也是一个抽象类,不可以生成实例。这里重要的是看看它的几个子类:Sprite 、Loader 、Stage 。Stage 就是舞台类。Loader 就有趣了,它把以前ActionScript 2的MovieClip 外部资源装载的这部分全部分离出来了。所有和外部资源的加载,都是通过Loader 来进行的。Loader 能干什么呢?装载swf 和各种图片。而Loader 对象也不能直接和网络资源打交道,要通过专门的URLRequest 对象来进行。各司其职,非常好。

·334

· 20.3.3 Sprite 和MovieClip

下面来讲解Sprite 类,这将是ActionScript 3 中与我们打交道最多的容器。如果用一句话描述它,那么可以把它看成是去掉了时间轴的MovieClip 。倘若我们只是为了创建一个容器,那么Sprite 是首选。写代码而非美工的开发人员,90%以上的情况都只需要和 Sprite 打交道。ActionScript 3中含有时间轴的MovieClip 通常都是由Flash 绘制工具(Flash CS3)创建出来的。Sprite 中也含有Graphic 对象,这意味着,它也可以直接在自身绘图。但我们始终要记住,Sprite 不同于Shape ,区别就在于Sprite 是容器,而Shape 不是。

都说到这儿了,ActionScript 3 中 MovieClip 还不见踪影,到底在哪儿?其实MovieClip 就是Sprite 的子类。Sprite 共有4个子类,MovieClip 是其中一个。ActionScript 3中的MovieClip 重要性大不如前了,在代码中主要用于表示Flash 绘制工具创建的含有时间轴的影片。只有MovieClip 对象才拥有和时间轴相关的属性和操作,比如ActionScript 2中很熟悉的 gotoAndStop()方法和currentFrame 属性。

20.3.4 *非Flash API 的几个显示对象类

在类图中左下方的3个类并不是Flash API 中的显示对象类,即不属于flash.*包中,但却是Flex 架构中非常重要的3个类。此处需要稍稍介绍一下。

这3个类中FlexSprite 和UIComponent 类都是处于mx.core.*包中,是Flex 组件架构的核心类。

FlexSprite 和Sprite 类的区别只是改变了一下toString()函数。FlexSprite 是Flex 组件UIComponent 类的父类。而mx.controls 里面的所有组件都是UIComponent 的子类。这两个类放在mx.core 包中当之无愧。

一个显示对象如果想被Flex 程序架构接纳,必须是UIComponent 类的子类或实现IUIComponent 的接口(Interface )。比如,UIComponent 就实现了IUIComponent 的接口。

所以,为了让Flash CS3中创建的MovieClip 能够在Flex 架构中使用,Adobe 出品了一个Flex Component Kit for Flash CS3 ,专门将现有的MovieClip 转成可以被Flex 架构接纳的元件。其中的关键就在于将现有MovieClip 对象转成mx.flash.UIMovieClip 的子类对象。由于UIMovieClip 实现了IUIComponent 子接口IDeferredInstaniationUIComponent ,从而UIMovieClip 对象都可以被Flex 架构所接纳。

20.4 ActionScript 3视觉架构的优越性

优秀的架构,必然带来一些激动人心的优越性。ActionScript 3花了大力气重新建立的显示编程架构果然不一般,它给我们带来了众多的便利,有着众多的优越性。下面扼要介绍最有代表性的五大优点。

flash ActionScript 3第20章 ActionScript 3视觉编程精要

·335·

20.4.1 更高效的渲染,更好的内存利用

ActionScript 3摒弃了ActionScript 2中臃肿的万灵药影片剪辑MovieClip ,将不同种类的显示任务分配给了不同的显示对象,极大地减少了内存的浪费,提高了渲染性能。比如,绘制矢量就使用轻量Shape 对象,需要容器就使用轻量的Sprite 对象。MovieClip 对象即使是在ActionScript 3中,虽然已经比ActionScript 2中的MovieClip 轻量不少,但也因为时间轴的支持而更加复杂一些。用于管理时间轴的属性会使用大量的内存和处理器资源。这样,将专门的工作分配给Shape 、Sprite 这些不需要时间轴的对象,可以提高性能,大大减少给内存和处理器资源造成的负担。

20.4.2 自动化的深度管理

在ActionScript 1和ActionScript 2中的编程中创建影片剪辑都必须考虑到深度的问题。但是,由于是ActionScript 2和ActionScript 1中的深度设计本身就有不妥,而且允许非连续深度,提供的管理API 也不够强大,这就使得深度的管理比较麻烦。在大型RIA 项目中,深度经常是一大头疼点。

在 ActionScript 3中显示对象深度由容器对象来自动管理,提供了更多的、更便捷的方法和属性。将显示对象移到 DisplayObjectContainer 对象的子级列表中的新位置时,显示对象容器中的其他子级会自动重新定位并在显示对象容器中分配相应的子索引位置。

此外,在 ActionScript 3中,总是可以发现任何显示对象容器中的所有子对象。每个DisplayObjectContainer 实例都有 numChildren 属性,用于列出显示对象容器中的子对象数目。由于显示对象容器的子级列表始终是索引列表,因此,可以检查列表中从索引位置 0 到最后一个索引位置 (numChildren - 1) 的所有对象。ActionScript 1和ActionScript 2中MovieClip 对象就很难做到这些。

在 ActionScript 3中,深度值是连续的,因此可以按顺序轻松显示遍历显示列表。遍历显示列表和管理对象深度比在ActionScript 1和ActionScript 2中更容易。在 ActionScript 3中,显示对象容器的每个子级列表都在内部缓存为一个数组,这样,按索引查找的速度就非常快。遍历显示对象容器所有子级的速度也非常快。

在ActionScript 3中,还可以通过使用DisplayObjectContainer 类的getChildByName()方法来访问显示对象容器中的子级。 20.4.3 完整遍历显示列表

在ActionScript 1和ActionScript 2 中,无法访问在 Flash 创作工具中绘制的某些对象(如矢量形状)。在ActionScript 3中,可以访问显示列表中的所有对象,包括使用 ActionScript 创建的对象及在Flash 创作工具中创建的所有显示对象。详细介绍请参见22.4.3节“遍历容器的子显示对象”。

·336· 20.4.4 列表外的显示对象

在 ActionScript 3中,可以创建不在可视显示列表中的显示对象。这些对象称为“列表外的”显示对象。要想在屏幕上显示这些对象,必须将显示对象添加到可视显示列表中。添加的方法是调用容器对象的addChild()或addChildAt()方法时,而且这个容器对象必须已添加到显示列表中。

通过将显示对象放在列表外,可以组合复杂的对象,而不需要占用处理时间来呈现这些显示对象。然后在需要时可以在显示列表中添加列表外的显示对象。此外,可以随意将显示对象容器的子级移入和移出显示列表及移到显示列表中的任何需要位置。这样,就可以使用列表外的显示对象来组合复杂的显示对象。

20.4.5 更易于创建自定义的显示对象

在ActionScript 1和ActionScript 2中,通常必须在 SWF 文件中添加新的 MovieClip 对象才能创建基本形状或显示位图。在 ActionScript 3中,DisplayObject 类包括许多内置子类,包括 Shape 和 Bitmap 。由于 ActionScript 3中的类更专用于特定类型的对象,因此更易于创建内置类的基本子类,即创建自定义的显示对象。

20.5 本章小结

本章从系统架构的思路出发,详细讲解了ActionScript 3中的视觉显示架构。阐述了一些重要的概念和思想,比如“一个统一,两个层次”——显示对象、可交互对象、容器,以及ActionScript 3应用程序的显示列表概念。通过和ActionScript 2的对比,突出了ActionScript 3显示架构的优越性。

本章中用大量的篇幅详细介绍了ActionScript 3的显示对象类库架构,捋清了整个显示架构的脉络分支,并阐述了相关的面向对象设计思想,以及揭示了显示对象所依据的设计模式——Composite 模式,供学有余力的读者继续研究。

相关主题
文本预览
相关文档 最新文档