ActionScript菜鸟教程

第1章 揭开ActionScript的神秘面纱

ActionScript是Flash内置的编程语言,用它为动画编程,可以实现各种动画特效、对影片的良好控制、强大的人机交互以及与网络服务器的交互功能。
ActionScript是一门吸收了C++、Java以及JavaScript等编程语言部分特点的新的语言。ActionScrip使用英文单词和元件提供了一种为Flash影片设置指令的方法。它的存在确保了Flash影片较之普通的按照线性模式播放的动画具备强大得多的人机交互能力。
可以为时间轴中的关键帧、按钮和影片剪辑添加ActionScript。选中这些关键帧、按钮和影片剪辑,打开其动作面板,你就可以看到它们都添加了哪些脚本。

1.1 Flash中的程序
交给计算机执行的指令集称为程序。程序的另一个名称叫做脚本。从现在开始,我们将这些指令集统称为脚本。
脚本都必须有它的运行环境,就ActionScript来说,它的运行环境就是Flash影片。ActionScript可以指挥Flash影片该做什么。在某些情况下,ActionScript还可以指挥其他的东西,如用户的操作系统、浏览器等。但是ActionScript最主要的用途还在于控制Flash影片内部的东西。
短的脚本可以只有一行,长的脚本可以长达几千行。它们可以作用于Flash影片的一个部分,也可以贯穿影片始终。有人把使用了脚本的整个Flash影片看作一个程序,也有人把影片中单独出现的脚本看作一个程序。这两种看法都正确,因为一个单独的程序也可以被定义成若干小程序。
你可能对某些编程语言已经相当熟悉或者有所了解。例如广大网页设计者所熟知的JavaScript,以及另一种相似的语言VBScript,它们能用来编辑动态网页。HTML(Hypertext Markup Language 超文本置标语言)是另一种特殊的语言,浏览器将按照它所包括的指令正确地显示文本和图片。
在学校里面,你可能接触过一些编程方面的课程,如BASIC、Pascal、C、Java等。
除HTML以外,以上提到的所有的语言都包含很相似的程序结构:循环、条件、变量等等。只要你知道了ActionScript的特殊用法,你就可以将以前所学的编程知识利用起来。就算你以前从来没有接触过编程方面的知识,不用担心,我会将所有需要的知识都告诉你。
1.2 ActionScript是从哪里来的
ActionScript是从哪里来的呢?事实上它的确是从好几种程序语言中深化而来的。下面我们先花一点时间了解一下计算机语言的起源和发展。
当第一台数字计算机诞生的时候,唯一的编程语言是计算机的专用语言——二进制代码,即由数字1和0组成的编码。当由1和0组成的不同序列被输入到计算机中,计算机就会执行完全不同的操作。使用这种语言编写程序是相当费劲的,就算写一个简单的两数相加的程序,程序的长度也是相当惊人的。
为了避免每次都为两数相加的操作书写长长的二进制程序,有人书写了一种专门用于两数相加的代码,你可以方便地使用相同的代码实现任意两数的相加操作。接着,一些类似的函数诞生了,用它们可以处理所有的基本任务,如加、减、乘、除、比较、循环等等。从此以后,你可以使用这些事先编写好的函数执行几乎所有的操作了。
现代的计算机语言理解和使用起来较之二进制编码都已经容易了无数倍,其一,现代计算机语言与英语语法很相似,如“go”、“for”、“begin”、“if”以及+、-、=等,它们的含义和用法与现实中都相差不大。
BASIC、Pascal等编程语言,几乎可以像英语句子一样阅读,所以学习和理解起来都非常容易。其他语言,如C、Fortran,它们的功能更强一些,经验丰富的程序员可以用它们完成更复杂的任务。更多的语言居于以上两种语言之间,如C++、Java和JavaScript,它们既有一定的可读性,也有较强的功能。ActionScript与这些语言有更多的相似之处。
Flash遵从ECMA(European Computer Manufacturers Association欧洲计算机工业协会)制定的标准,因此ActionScript与ECMAScript(ECMA开发的一种语言)极其相似。所以与其说ActionScript建立在JavaScript的基础上,不如说ActionScript和JavaScript都建立在共同的基础之上。
Flash具备交互功能,它的早期版本已能够利用简单的脚本实现不太复杂的导航和按钮。同时,Flash还是一种矢量动画工具,它的发展是与对它的应用需求分不开的,比如说网页设计者需要一种工具来制作体积更小的图像,由于矢量图是由线条和填充色构成的,而不是像位图一样由像素构成,所以它能够大大缩减文件大小,正顺应了网页设计者的需求,使许多系统配置低的用户也能够访问和浏览他们的网页。
虽然说Flash是一个图形动画工具,但也不是没有使用程序的需要,比如说设计者需要制作一个按钮,让别的用户能通过单击按钮浏览到别的页面。
Flash早期版本中的脚本非常简单,直到Flash 4,才具有了标准的程序结构,如条件结构、循环结构等。但是Flash脚本仍然需要使用下拉菜单和空白文本框添加,几乎还不能叫做一种编程语言。
真正的ActionScript到了Flash 5才出现,程序员可以直接键入程序并将程序添加给需要作用的元素。Flash MX更大地扩展了ActionScript,现在的ActionScript提供了多达300余种命令、函数、运算符和结构,这才真正成为一种成熟的程序语言。
1.3 初识ActionScript
脚本是由英语单词、数学符号和函数构成的,下面是一个ActionScript的例子:
on (press) {
gotoAndPlay ("my frame");
}
你可以通过其中的关键单词推测这段程序的作用。单词press表示按,即用鼠标在某种对象上面单击,这里的对象就是按钮。第二行中的长单词可以分开读成“go to and play”,可以将其理解为命令Flash到达影片中的一个特定位置并从这一特定位置开始播放影片。
从以上可以看出,ActionScript可以控制Flash影片的播放。在着手学习ActionScript之前,我们将对ActionScript在Flash影片中的功能作更多的了解。
Flash影片可以包含若干场景,每个场景都有时间轴,每条时间轴从第1帧开始。如果不添加ActionScript,Flash影片会自动从场景1的第1帧开始播放,直到场景1的最后一帧,然后接着播放场景2,以此类推。
ActionScript的主要目的就是用来改变这种自动而死板的线性播放行为,一段脚本可以使影片在一个特定的帧上停止,循环播放前面的部分,甚至于让用户控制要播放哪一帧。ActionScript能够使影片完全脱离被动的线性播放模式。
这还不是ActionScript的所有功能,它还可以将Flash影片从简单的动画改变为具有交互能力的电脑程序。下面让我们见识一下ActionScript能实现的一些基本功能。
= 控制播放顺序
你可以通过选择某个菜单将影片暂停在某个位置,然后由用户来决定下一步干什么,这就避免让影片径直朝前播放。
= 创建复杂动画
直接使用Flash中的绘图工具和基本命令来创建足够复杂的动画是相当困难的,但是脚本可以帮助你创建复杂的动画。例如可以用ActionScript控制一个球在屏幕中无休止的跳动,并且可以使它的动作遵从物理学中的重力定律。如果你不用ActionScript来实现这样的动画,你将需要几千帧来模仿相似的动作,而用ActionScript,你将只需要一帧。
= 响应用户输入
你可以通过影片向用户提出问题并接收答案,然后将答案信息用于影片中或将其传送到服务器。加入了相应ActionScript的Flash影片更适合做网页中的表单。
= 从服务器获取数据
与向服务器传送数据相反,使用ActionScript也可以从服务器中获取数据,你可以获取即时的信息并将它提供给用户。
= 计算
ActionScript也可以对数值进行计算,用它可以模拟出各种复杂的计算器。
= 调整图像
ActionScript可以在影片播放时改变图像的大小、角度、旋转方向以及影片剪辑元件的颜色等。你还可以从屏幕中复制或删除对象。
= 测试环境
你可以用ActionScript测试Flash影片的播放环境,如获取系统时间,获取Flash Player的版本信息等。
= 控制声音
ActionScript可以方便地控制声音的播放,甚至控制声音的声道平衡和音量等。
1.4 ActionScript放在哪里
初学ActionScript的Flash爱好者最想问的问题恐怕是“ActionScript应该放在哪里?”
Flash是一种复杂的多媒体编辑环境,如果你曾经使用过Flash,或者看过Flash MX附带的教程,你就应该知道Flash中的一些基本术语或元素。在Flash的元素中有3个地方可以放置脚本。
1.4.1 时间轴
Flash影片中的每个场景都有时间轴,时间轴上的每个关键帧都可以放置脚本。并且,你还可以在每一个关键帧的不同层上放置不同的脚本。
在主时间轴中放置脚本之前,需要先选择一个关键帧。启动Flash时,时间轴中有一个空白关键帧
当选中一个关键帧后,你就可以打开动作面板,查看里面的脚本或者开始编写你自己的脚本了。
有几种方法可以打开动作面板。你可以选择“窗口”→“动作”命令,或者按快捷键F9。
如果你对Flash复杂的影片浏览器比较熟悉,你也可以在影片浏览器中查看整个Flash影片所用到的脚本。打开影片浏览器的快捷键是Alt+F3。
如图1-2所示即为Flash MX的动作面板。该动作面板被命令为“动作-帧”,这是因为其中的脚本将作用在帧上。如果是新建的一个影片,动作面板将是空的。后面我们将在动作面板中添加各种各样的脚本。第2章我们将看到如何使用动作面板。
时间轴中的脚本将在Flash影片播放到脚本所在的关键帧位置时自动执行。例如,如果你为某一关键帧添加了stop()命令,当影片播放到那一帧位置时就会自动停止。要让影片继续播放,只有在其他的脚本中添加相应的命令。
在时间轴中添加脚本还有一个好处就是方便你在ActionScript中使用函数。函数是可以重复使用的脚本代码,要想使整个影片都可以调用脚本中的函数,就必须将函数放置在主时间轴中。
1.4.2 按钮
Flash中的元素又称作元件(symbol)。元件主要有3种:图形(graphic)、影片剪辑(movie clip)和按钮(button)。图形元件不能承载脚本,它们只能是简单的静态或动态图像。影片剪辑与图形元件类似,但是它可以承载脚本。
第3种元件就是按钮,按钮可以承载脚本。事实上,如果没有脚本,按钮几乎不会发挥什么作用。
要为按钮添加脚本,首先要在舞台中选中按钮,然后选择“窗口”→“动作”命令或按快捷键F9打开动作面板。
与帧动作面板相对应,选中按钮时动作面板的标题是“动作-按钮”。
你可能会认为,为按钮添加的脚本应该是在单击按钮时执行。其实,也可以为其他鼠标动作添加相应的脚本,如鼠标进入和移出按钮区域。按钮也可以响应按键动作,这使得我们可以方便地为按钮设置快捷键。
1.4.3 影片剪辑
影片剪辑不同于图形元件,可以为影片剪辑命名,为影片剪辑添加脚本。为影片剪辑添加脚本的方法与按钮类似。
为影片剪辑添加的脚本可以用来控制影片剪辑自身或控制时间轴中的其他影片剪辑。使用脚本可以判断影片剪辑出现在屏幕中的什么位置,你也可以用脚本来控制影片剪辑的重复播放等,进而控制整个动画。
除了可以为影片剪辑添加脚本,你也可以在影片剪辑内部添加脚本。影片剪辑其实也是一个单独的Flash影片,在影片剪辑中有一条单独的时间轴,你可以像在主时间轴中添加脚本一样在影片剪辑内部的时间轴中添加帧动作脚本。同样地,你也可以将按钮放置到影片剪辑内部并为按钮添加脚本。也就是说主时间轴中的影片剪辑里面有子影片剪辑,子影片剪辑里面又有按钮,按钮中也可以有影片剪辑,如果需要,你都可以为它们添加脚本。
1.5 练习:你的第一段ActionScript
下面来编写你的第一段ActionScript,让你对ActionScript有更深的了解。操作步骤如下:
(1)创建一个新的Flash文档。
(2)选中时间轴中的第1帧,按F7键两次插入两个空白关键帧,这时时间轴中应有3个空白关键帧。
(3)在每一帧中绘制不同的图形。
(4)选择“控制”→“测试影片”命令或按Ctrl+Enter键测试影片,你会看到影片在这3个帧之间循环播放。
(5)回到主时间轴,选中第2个关键帧,按F9键打开动作面板。
(6)动作面板左边显示了可扩展的ActionScript关键字目录。在“动作”/“影片控制”目录下面找到关键字stop并双击,脚本窗口将添加如下所示的一行语句:
stop();
(7)关闭动作面板,按Ctrl+Enter键测试影片,播放第1、2帧后影片会停止,你将看不到第3帧。
ActionScript发挥了作用,它成功地阻止了影片无休止地循环播放这3帧。

 

第2章 Flash MX的动作面板

动作面板是Flash MX面板系统的一部分,ActionScript程序员经常会用到它。为了成长为一名娴熟的Flash编程高手,你有必要对Flash的动作面板和在线帮助系统相当的熟悉。
动作面板的标准模式允许你从脚本目录中选择关键字并设置相应的选项,而专家模式为程序员提供了直接输入代码的自由。

2.1 了解动作面板
Flash MX的面板系统向你提供了查看和设置Flash中各种元素信息和属性的捷径。第一次启动Flash MX的时候,系统将会询问你要使用Flash做哪些方面的工作,然后为你设置默认的面板界面。你可以选择“窗口”→“面板设置”命令在不同的面板界面之间切换。与此同时,也决定了动作面板的大小,但是你可以将它改变成任何适合你需要的大小。
你可以通过键盘上的F9键随意显示或隐藏动作面板。显示动作面板后,你可以单击它的标题栏将它展开或折叠起来。你还可以拖动动作面板的左上角将它从Flash的工作界面中分离出来。
动作面板有两种不同的工作模式。默认的模式是标准模式。在标准模式下,你必须从窗口左边的菜单中选择需要的关键字,而不能直接使用键盘输入脚本,因此可以有效避免即使是很细小的错误。
2.2 动作面板的标准模式
面板上部的下拉菜单显示了你当前所编辑的脚本的准确位置。图2-1中显示的是“帧动作脚本1 图层名称 图层1”,也就是说当前所编辑的脚本是作用于图层1的第1帧的。
面板左边显示了ActionScript命令的分类目录,单击展开一个目录,你将看到它里面的子目录或命令。
面板的右边是一个空白文本区,它将显示你所选择的命令和函数。图2-2显示了你从左边的目录里面选择插入“动作”→“影片控制”中的goto命令后的动作面板。goto命令是通过双击鼠标添加到脚本中的。
面板右上部显示了goto命令的简单定义,下面显示了与goto命令相关的各种选项,包括“场景”、“类型”和“帧”等,就像是所选命令的参数设置区。参数设置区的状态会依据所选择ActionScript命令的不同而发生变化。
第一个需要设置的选项是选择gotoAndPlay命令还是选择gotoAndStop命令。图2-2中选中的是“转到并播放”单选项,也就是gotoAndPlay。这两种命令是相似的,都是跳转到特定的帧,但是gotoAndPlay命令使影片从特定帧开始播放,gotoAndStop命令使影片在特定帧上停止。
这个命令还需要附加一些信息才能正常工作。如,你想要使影片跳转到哪一帧,这一帧位于哪个场景,图2-2指定的是当前场景。在“类型”下拉菜单中可以选择指定特定帧的方式,你可以使用帧号、帧标签和表达式中的一种。图2-2选中的是帧号类型,这就要求你精确地指定帧的编号,如1。
在以上内容的下面显示了 和 两个按钮。它们使你可以快速地在脚本中插入和删除命令。但是这种方法很少使用,你可以通过左边的分类目录添加脚本,使用键盘上的Delete或Back Space键删除不需要的命令。
和 按钮的右边还有几个功能不一的按钮。 按钮使你可以从脚本中查找文本, 按钮使你可以替换文本,使用 按钮可以插入目标路径, 按钮可以为你调试脚本设置断点, 和 按钮使你可以选择脚本的前一行或后一行。
在动作面板的底部你可以看到这样的一行:“第1行:gotoAndPlay(1);”,这是动作面板的状态行,它显示了当前选中的行号和该行的内容。
2.3 分类目录
动作面板左边的目录将ActionScript的关键字有组织地分成几组,以使你更容易查找到需要的关键字的位置。以后我们会对每个组中的命令和符号作详细的讲解,下面先对其进行一下简要的介绍。
= 动作
在动作类中包含了最简单的ActionScript命令。动作类提供了测试条件、循环、创建函数、复制和创建影片剪辑以及从服务器中获取数据等功能的命令。动作类中的命令是ActionScript最重要的组成部分。动作类又分为影片控制、浏览器/网络、影片剪辑控制、变量、条件/循环、打印、用户定义的函数以及其他动作等子类。
= 运算符
它包括了各种数学和比较运算符,如+号,用于两数相加;==号,用于判断两数是否相等。运算符类下面又分为按位、比较、赋值、逻辑、算术和其他运算符等子类。
= 函数
使用函数可以转换数据或获取需要的信息,如获取Flash的版本信息。你可以使用函数将字符串123转换成数字123。你还可以自定义需要重复使用的函数。在函数类下面主要有两个子类:数学函数和转换函数。
= 常量
常量类中包含了一些具有特定值的特殊关键字,如true、false、null和newline等。
= 属性
属性类中的关键字反映了Flash中元素的相关信息。例如_x属性代表影片剪辑在屏幕中的水平位置。
= 对象
对象类是最复杂的一类,它包含了ActionScript中的众多概念。所有的对象关键字被分成4个子类:核心、影片、客户端/服务器、创作。影片剪辑是影片类下面的一种,它包含了与控制影片剪辑相关的关键字。Math是核心下面的一种,它包含了求平方根、正弦值等数学函数。
= 否决的
这一类中的关键字是已经作废但Flash MX仍然支持的,在Flash MX中请尽量避免使用,因为在以后的Flash版本中将不再支持这些关键字。
= Flash UI组件
这一类中的关键字包含了特殊功能的组件,如单选按钮、滚动条等。
= 索引
索引类将ActionScript中的所有关键字按字母顺序排列。以上各类中的关键字都可以在索引类中找到。
动作面板中提供的关键字分类有时可以帮你方便地找到需要的关键字,但也有可能给你带来麻烦。如你可能认为表示影片剪辑水平坐标属性的_x应该在对象类的“影片”/“影片剪辑”/“属性”里面,但它却在属性类里面。你可能认为sqrt(开平方)应该在函数类中,但它却在“对象”/“核心”/“Math”/“方法”下面。
2.4 使用Flash的帮助系统
最好的程序员往往也要查阅一下工具书,Flash中的帮助系统就是一本功能强大的工具书,所以在学习更多内容之前,先了解一下Flash的帮助系统,将对我们的学习不无陴益。
Flash使用工具提示和基于扩展HTML的帮助系统。为了对ActionScript的使用更加娴熟,你就需要知道如何使用它们。
2.4.1 简单定义
如果你习惯使用动作面板中的关键字分类目录,你应该会注意到当你在左边的目录中选中某个关键字时,面板右边的上面部分会给出与所选关键字相应的简单定义。你会看见这样的句子:“要添加某项,可双击该项或将其拖动到脚本窗口。
例如选中goto命令时,你会看到这样的提示:“转到影片的指定帧。”它显示了该脚本的基本功能。
单击别的命令查看一下它们的定义,在学习下面的知识之前,你可以花些时间多看一下动作面板中的命令。
2.4.2 脚本参考面板
Flash使用脚本参考面板帮助你记住ActionScript的语法。可以选择“窗口”→“脚本参考”命令或按快捷键Shift+F1打开脚本参考面板。
脚本参考面板的左边与动作面板左边的脚本目录很相似。你也可以通过动作面板进入脚本参考面板,单击动作面板中的 按钮可以打开脚本参考面板,打开的脚本参考面板会自动显示你在动作面板中选中的命令。
2.4.3 HTML帮助文档
如果要获得ActionScript命令更详细的说明,可以选择“帮助”→“动作脚本词典”命令,这将启动你的浏览器并打开如图2-4所示的页面。

图2-4 动作脚本词典
浏览器窗口的左边是所有ActionScript命令和函数的总目录,在左边的条目上单击,窗口的右边部分会显示其详细的内容。
选中每个条目时,右边窗口中通常会包括与该条目的说明以及它的使用范例。
在你以后使用Flash的时候可能经常会用到帮助文档,所以请花一些时间了解它吧。
2.5 动作面板的专家模式
现在你已经了解了动作面板的标准模式,下面要向你推荐多数ActionScript程序员使用的专家模式。
在专家模式下,你可以直接通过键盘输入脚本,而不需要从左边的目录中选择命令。这种模式下你可以在动作面板中输入任何东西,但也很容易导致错误。
在专家模式下,你仍然可以从左边的目录中选择并插入标准的ActionScript命令、函数和运算符。当你记不确切一条命令的时候就可以使用这种方法。
2.5.1 切换模式
要从标准模式切换到专家模式,可以单击动作面板中的 按钮,或者单击动作面板右上角的 按钮,在打开的下拉菜单中选择“专家模式”命令。在动作面板获得焦点的情况下,快捷键Ctrl+Shift+N可以切换到标准模式,快捷键Ctrl+Shift+E可以切换到专家模式。
如图2-5所示为专家模式下的动作面板。在专家模式下,参数设置区、命令提示信息都没有了,脚本编辑窗口占据了动作面板右边的大部分。
从标准模式切换到专家模式是非常容易的,但是要从专家模式切换到标准模式则要求脚本中没有语法错误。比如说你不明白如何设置一些命令的参数,需要从专家模式切换到标准模式以使用标准模式下的提示,但是Flash却不允许你进行切换,提示你“此脚本中有语法错误,必须在‘专家模式'下编辑它”;而当你知道如何设置参数并将脚本书写正确了,又不再需要切换到标准模式了。
2.5.2 动作面板的下拉菜单
动作面板的下拉菜单中有一些特别是在专家模式下编辑脚本时很有用的命令。
你可以使用查找和替换命令在代码中执行查找和替换操作。按快捷键Ctrl+F可以打开“查看”对话框,按快捷键Ctrl+H可以打开“替换”对话框。
“转到行…”命令可以快速转到并选中指定的行。
“语法检查”命令或按钮 可以对窗口中的脚本进行语法检查,如果没有语法错误,将提示你“此脚本中没有错误。”
通常,语法检查只能检查出代码中的明显语法错误,它并不能检查脚本是否能正确运行。经常会发生这样的事情,就是每一行的代码都是正确的,但所有的代码加在一起却导致了错误。
语法检查功能很实用,特别是对初学者来说,它能方便地检查出误用运算符或缺失括号等情况。
“自动套用格式”命令可以按预先设置的样式和缩进等设置脚本的格式。你可以选择“自动套用格式选项”命令,在“自动格式选项”对话框中重新设置要应用的格式,
另外,选择“首选项…”命令可以设置动作面板中脚本代码的颜色、制表符宽度、字体等。你也可以在Flash MX的菜单栏中选择“编辑”→“首选参数”命令,在打开的“首选参数”对话框中选中“动作脚本编辑器”选项卡,打开相同的对话框,如图2-7所示。

图2-7 “首选参数”对话框
为脚本上色有利于编写程序。使用这项功能时,你将看到ActionScript中的关键字以一种颜色显示,而另外一些变量和常数以另外的颜色显示。这对初学者是很有帮助的。如正确输入关键字gotoAndPlay后,它马上会以蓝色显示。如果它的颜色没有发生变化,有可能就是你的输入有误。
动作面板下拉菜单中还有导入导出文件以及打印等命令,可以将使用外部的文本编辑器编辑好的脚本导入到动作面板中,或将动作面板中的脚本导出或打印出来。
从外部导入脚本的方法并不值得推荐,因为动作面板虽然不是最快捷的文本编辑器,但是在其中编辑ActionScript是最好的,你可以在需要的时候参照脚本分类目录,可以即时的查看Flash中的影片剪辑的名称,查看帧编号或帧标签。另外,你还可以快捷地切换到Flash影片中要插入脚本的任何位置。
2.5.3 在专家模式下输入脚本
使用动作面板的专家模式要比标准模式容易得多,因为在专家模式下你只需要敲击键盘,而不需要在窗口中填写表格。专家模式下的动作面板就像一个简单的文本编辑器。
使用专家模式的缺点就是很容易出错。标准模式为你添加了很多限制,而在专家模式下你有可能键入不正确的命令或者将参数放错位置。
在专家模式下,你可以方便地将光标定位在合适的位置。但是Flash也不能完全任你随心所欲,它会在你键入的同时自动调整脚本格式,将不同的关键字设置成不同的颜色。
你可以单击 按钮以检查脚本中的语法错误,单击 按钮以格式化整个脚本,如在需要的位置换行、设置空格和缩进等。
动作面板还有代码提示的功能。当你键入脚本的时候有时会出现一个提示菜单,你可以忽略它继续键入,或者从中选择需要的项目。单击 按钮可以显示代码提示。
2.6 练习:在专家模式下输入脚本
下面我们练习在专家模式下输入脚本。其操作步骤如下:
(1)新建一个文档。
(2)选择默认的场景1图层1中的第一个空白关键帧。
(3)按F9键打开动作面板。
(4)使用菜单将动作面板切换到专家模式。
(5)在脚本编辑区单击。
(6)键入下面的一行代码:
gotoAndPlay(5);

 

第3章 ActionScript编程初步

计算机程序是由命令、函数、运算符、条件和循环等结构组成的。命令是为计算机下达的一系列指令,函数执行计算和返回值,通过运算符将若干数据以某种特定的方式结合起来,条件测试一个或多个值以返回一个为true或false的布尔值,循环结构使得程序能够重复执行一系列相同的指令。
变量是存储数据的容器,变量有变量名和变量值。
编程是一项需要耐心的工作,首先你必须理解要用程序解决什么样的问题,然后需要将这个问题分解成若干步骤,将每个步骤再分成更小的步骤,直到每个步骤都小得很容易解决了为止。
程序编写好后,可能会存在许多漏洞或缺陷,所以你还需要对程序进行调试,直到程序能正确运行为止。

3.1 程序基本结构
计算机程序是由命令、函数、运算符、条件和循环等结构组成的。
3.1.1 命令、函数和运算符
在此之前,我们都是用关键字来描述ActionScript中的元素,如关键字gotoAndPlay,它也是一个命令。
命令是ActionScript中用来告诉Flash所要执行的特定操作的元素。之所以称之为命令,就是因为它将被严格的遵照执行,如果要用gotoAndPlay跳转到一个不存在的帧,这样的命令就不能被执行。
命令是程序中最基本的元素,在Flash中如果不使用命令,几乎不能进行任何操作。从本书中你将学到很多命令。
函数是ActionScript中用来执行计算和返回结果的元素。例如,一个特定的函数可以计算并返回一个指定数的平方根。
命令和函数都可以使用参数。参数就是传递给命令或函数的一个值。如gotoAndPlay命令就至少需要一个帧编号或帧标签作为参数。求平方根的函数也需要一个数值作为参数。
与命令和函数不同的是运算符,它们主要是一些符号,而不是字母。例如,+运算符执行两数相加的操作。
在ActionScript程序中你将会用到大量的命令、函数和运算符。
3.1.2 变量
要编写复杂的计算机程序往往需要存储很多的信息。有时你可能只需要存储很短暂的时间,例如,如果需要重复执行10次相同的命令,你就需要对命令的执行次数进行记数,直到满10次为止。
所有的编程语言都使用变量来存储信息。一个变量由两部分构成:变量名和变量的值。
1.变量名
变量名通常是一个单词或几个单词构成的字符串,也可以是一个字母。总的来说,你需要尽可能地为变量指定一个有意义的名称。
例如,如果你要使用变量存储用户的姓名,用userName作为变量名将是一个很好的选择。如果你使用n作变量名,似乎太短了一点;如果使用name,又可能与影片中其他对象的名称相混淆。
在ActionScript中为变量指定变量名时已经形成了一种不成文的规范,就是变量名通常以小写字母开头,当一个新的单词出现时,大写这个新单词的第一个字母,如userName,长一点的例子如currentUserFirstName。
变量名中不允许出现空格,也不允许出现特殊符号,但是可以使用数字。
2.变量类型
你可以用变量存储不同类型的数据。数字是最简单的变量类型。
你可以在变量中存储两种不同类型的数字:整数和浮点数。整数没有小数点部分,如117、-3685都是整数。浮点数有小数点部分,如0.1、532.23、-3.7都是浮点数。
你也可以在变量中存储字符串,字符串就是由字符组成的序列,可以是一个或多个字符,甚至可以没有字符,即空字符串。
使用引号定义字符串,使其与其他变量相区别。如7是一个数字,而“7”则是一个字符串,这个字符串由一个字符7组成。
在别的编程语言中,你可能需要在程序的开头部分提前定义程序中要用到的变量的具体类型,但在ActionScript中不需要预先声明变量,你只需要直接使用它们,Flash在第一次遇到它们的时候会自动为它们创建变量。
另外,变量所能存放的数据类型也没有严格的限定,某一变量可以在一个位置存放字符串,而在另一个位置存放数字。
这种灵活性并不是经常用得到,但是它可以让程序员们少一些不必要的担心。
ActionScript程序员不必担心的另一个问题是废弃变量的空间回收问题。即当你不再需要使用一个变量的时候,你可能需要收回该变量占用的存储空间。大多数现代的计算机语言如ActionScript都可以自动回收空间,所以你也不必担心了。
除数字和字符串类型外还有一些别的变量数据类型。例如,数组可以存放一系列的数据而非单个数据。
3.1.3 条件
程序本身并不能作出抽象的决定,但是它可以获取数据,并对数据进行分析比较,然后根据分析结果执行不同的任务。
例如,你想要检查用户输入的名字并确定其至少包含3个字母。程序需要做的事情就是对用户名作出判断,如果是3个或更多的字母,就执行一种操作;如果不足3个字母则执行另一种操作。
这里,作出一个决定需要两步,第一步是检查条件是否满足,如果名称符合3个字母长度,条件满足,我们称条件的值为真(true);否则条件不满足,我们称条件的值为假(false)。所有的条件都必须是两个值中的一种,要么为真,要么为假。要么为真(true)要么为假(false)的数据类型称为布尔(boolean)类型。
决定的第二步是根据条件为true或为false的情况选择要执行哪些代码。有时只有一个选项,当条件为true时执行该选项;如果条件为false,将不执行任何代码。有时会有两个相对的选项,条件为true和false时分别执行不同的代码。
例如,你想让计算机根据一个变量的值是1、2或3执行3种不同的任务,可以像这样表达:
如果变量的值等于1,执行命令1
如果变量的值等于2,执行命令2
如果变量的值等于3,执行命令3
条件总是建立在比较之上的,你可以比较两个变量的值以判断它们是否相等;或者判断一个是否大于另一个,或是小于另一个。如果变量是字符串类型,你可以比较它们按字典顺序排列时的先后次序。
3.1.4 循环
与人不同,计算机很适合做重复性的工作。一件事情仅仅重复几次就可能使人厌倦,但是让计算机重复执行成千上万次它都照样有耐心。
循环在每种编程语言中都是一个很重要的部分,ActionScript也不例外。你可以指定一条指令执行给定的次数,或者令其执行到满足指定的条件为止。
事实上,条件是循环中的重要组成部分,整个循环只需要一个开始点,一个结束点,再加上一个标志循环结束的条件。
例如,你需要循环10次,使用一个变量从0开始计数。每循环一次,计数加1。当计数变量达到10时,循环结束,程序继续执行循环以后的部分。下面的内容代表了一个标准的循环结构:
(1)循环以前的命令。
(2)循环开始,计数变量置0。
(3)循环中的命令。
(4)计数变量加1。
(5)如果计数变量小于10,执行步骤(3)。
(6)循环以后的命令。
在上面的步骤中,步骤(1)只执行1次,步骤(2)表示循环的开始,步骤(3)、(4)、(5)都将执行10次,当循环结束后,执行步骤(6)及以后的部分。
3.2 ActionScript之一角
当你在编写自己的脚本时,你会用到各种各样不同的关键字和符号,为便于你熟悉脚本的构成,下面先来看一个真实的例子。
这是一段作用于按钮的脚本,当用户单击按钮时(确切地说是松开按下的按钮时)执行它。其中没有包含特殊的函数,但是它体现了ActionScript的主要结构。
on (release) {
var myNumber = 7;
var myString = "Flash MX ActionScript";
for (var i=0; i<myNumber; i++) {
trace(i);
if (i + 3 == 8) {
trace(myString);
}
}
}
脚本的第1行表明当用户松开按下的按钮时执行大括号中的语句。on (release)结构只能用于按钮,其他相关的几种用法如on(press)、on(rollOver)、on(rollout)、on(dragOver)、on(dragOut)等。
第1行末尾的大括号{表示一段相对独立的代码段的开始。从{到与之相对的}之间的代码是一个整体,它们都从属于按钮的release事件。
请注意,大括号之后的代码较之第1行有一个制表符(按一次Tab键)的缩进,其后的每行代码与之具有相同的缩进程度,直到一个新的大括号开始,在新大括号后的语句会比前面的语句增加一个制表符的缩进,以此类推,这种特点与其他编程语言是类似的。Flash会自动将你添加的代码设置成正确的缩进样式。
代码的第1行创建一个名为myNumber的局部变量,并将该变量的值设置为7。下面一行将字符串Flash MX ActionScript赋给另一个变量myString。稍后我们会更详细的介绍变量的两种类型:局部变量和全局变量。
分号;表示一条指令的结束,在每个完整指令的末尾都应该添加分号。
for代表一个循环结构的开始,此处的循环执行7(myNumber)次,即令i从0递增到6,每递增1便执行一次循环结构中的语句。for后面大括号中的部分即为循环体。
命令trace将它后面括号中的内容发送到输出窗口。我们将在下一部分详细介绍输出窗口。
if是一种条件结构,它测试后面的内容i + 3 == 8是否为true,如果为true,则执行后面的语句;否则跳过该代码段。
if结构中只有一个trace命令,它将变量myString的值发送到输出窗口。
上例脚本以三个反向大括号}结束,第1个表示if语句的结束,第2个表示for语句的结束,第3个表示整个on(press)段结束。
3.3 输出窗口
输出窗口是只在测试Flash影片时出现的一个编程工具,Flash用它来显示出错信息或其他的一些重要信息。用户可以用ActionScript中的trace命令自定义要发送到输出窗口中的信息。
输出窗口在测试程序时非常有用。你可以使用trace命令在输出窗口中显示变量的值或者哪一部分ActionScript正在执行。
输出窗口还可以帮助你学习ActionScript。你可以编写一些小程序,将信息发送到输出窗口,这将帮助你看到程序的运行结果。
要想熟悉输出窗口,最好的方法就是多使用它。下面就来编写一段小程序,将信息发送到输出窗口。
(1)启动Flash MX。
(2)选中时间轴的第1帧,打开第1帧的动作面板。
(3)使用右上角的菜单将动作面板切换到专家模式。
(4)在脚本编辑区单击鼠标,将鼠标光标定位到脚本编辑区中。
(5)在动作面板中输入如下ActionScript:
trace("I like ActionScript!");
(6)按Ctrl+Enter键测试影片,因为舞台中没有任何图像,所以你将看到一个空白窗口,同时出现一个输出窗口,窗口中显示:I like ActionScript!如图3-2所示。 输出窗口显示了trace命令中的信息
和动作面板一样,输出窗口右上角也有一个下拉菜单,其中包含了拷贝、清除、查找、保存到文件以及打印等命令。
下拉菜单的最后一项命令是“调试级别”,你可以选择“错误”、“警告”、“详细”中的一种,如果选择“无”,将不显示任何信息。
3.4 ActionScript基本语法
前面介绍了程序的基本结构,下面要讲解ActionScript中的基本语法。
3.4.1 变量
1.设置变量
在ActionScript中使用变量的方法很简单,你只需要为变量名分配一个值,例如:
myVariable = 7;
该例在创建名为myVariable的变量的同时将其值设置为7,你可以为变量任意取一个名字,而并不需要使用本例中的myVariable。
可以使用输出窗口查看变量的值,如在一个空白影片第一帧的动作面板中添加如下ActionScript:
x = 7;
trace(x);
首先,数字7被存储在变量x中;然后,使用trace命令将变量x的值发送到输出窗口。影片播放时,输出窗口中会显示数字7。
2.全局变量
根据变量作用的范围不同可将变量分为全局变量和局部变量。
全局变量就是可以作用在整个Flash影片的所有深度级别上的变量。你可以在某一帧中设置它,并在其他帧中使用和改变它的值。
你不需要使用特别的方法创建全局变量,像前一个例子一样,直接设置并使用它,它自动成为一个全局变量。
在许多编程语言中,全局变量可以在任何地方使用。Flash影片使用一个概念叫层级(level)。整修影片的主时间轴作为根(root)层级,影片剪辑是时间轴中的小影片。影片剪辑中的图形和脚本要比根层级低一个级别。影片剪辑不能直接使用根层级中的全局变量。
3.局部变量
局部变量只能存在于当前脚本中,而在其他帧中它将不再存在。你可以在使用同一个变量名在不同的帧中创建不同的局部变量,它们之间将互不影响。
局部变量可用来创建模块化的代码。当前脚本执行完时,局部变量将被从内存中删除;而全局变量将保留到影片结束。
创建局部变量需要使用关键字var。例如,下面的ActionScript创建值为15的局部变量myLocalVariable:
myLocalVariable = 15;
使用var创建局部变量后,在当前代码中就不再需要使用关键字var了。例如,下面的代码创建值为20的局部变量myLocalVariable,然后将其值改为8,再发送到输出窗口中。
var myLocalVariable = 20;
myLocalVariable = 8;
trace(myLocalVariable);
如果没有特殊的需要,请尽量使用局部变量。
3.4.2 比较
在ActionScript中比较两个事物是很容易的,要进行比较可以使用标准的数学符号,如=、<、>等。
1.相等
在ActionScript中用比较运算符对两个值进行比较。
要比较两个值是否相等,可以使用连在一起的两个等于符号(==)。单个等于符号(=)是用来为变量分配值的,并不是比较运算符。
如果要比较变量x的值是否等于7,就可以使用==符号,如下所示:
var x = 7;
trace(x == 7);
以上代码使用=符号将变量x设置为7,然后使用==符号对x和7进行比较。
测试这两行代码,输出窗口将显示“true”。如果将x设置为8或其他数,则会显示“false”。
==符号还可以用来比较两个字符串。如下所示:
var myString = "Hello ActionScript.";
trace(myString == "Hello ActionScript.");
trace(myString == "hello ActionScript.");
程序运行时,你将在输出窗口中看到一个“true”和一个“false”,因为在字符串中字母是要区分大小写的。
如果你要比较两个值是否不等,可以使用!=符号,它的意思是“不等于”。如下所示:
var a = 7;
trace(a != 9);
trace(a != 7);
第1个trace语句显示信息“true”,因为a确实不等于9;第2个trace语句显示信息“false”。
2.小于和大于
使用标准的数学符号<和>比较两数是否成小于或大于关系。举例如下:
var a = 9;
trace(a < 10);
trace(a > 5);
trace(a < 1);
你将从输出窗口中看到“true”、“true”和“false”。
符号<=或>=用于比较一个数是否小于等于或大于等于另一个数,如下所示:
var a = 9;
trace(a <= 9);
trace(a >= 9);
trace(a >= 7);
以上3个trace语句都将显示“true”。
3.4.3 运算
通过运算可以改变变量的值。分别使用算术运算符+、-、*、/执行加、减、乘、除操作。
如下所示的ActionScript将值为9的变量x加上一个数7:
var x = 9;
x = x + 7;
trace(x);
运算结果为16。
在ActionScript中执行运算可以使用一些简写方法,如+=运算符将其前后的值相加并将结果赋给它前面的变量。前面的脚本也可以写成如下的形式:
var x = 9;
x += 7;
trace(x);
++运算符与+=运算符类似,但它每执行一次,变量的值只增加1,如下面的例子:
var x = 9;
x++;
trace(x);
结果显示10。再看下面的例子:
var x = 9;
trace(x++);
trace(x);
结果是9和10。为什么呢?因为第1个trace语句输出x的当前值9,然后将x加1,输出x的新值10。
再试一下下面的脚本:
var x = 9;
trace(++x);
trace(x);
这次的结果为两个10。因为将++运算符置于变量前面,将先执行运算再返回变量的值。
同理,–运算符执行递减操作,-=运算符在变量当前值的基础上减去一个数,*=运算符在变量当前值的基础上乘上一个数,/=运算符在变量当前值的基础上除以一个数。
3.4.4 条件
既然现在你已经知道如何比较两个变量,你就可以将比较结果作为执行某些语句的条件。
1.if语句
if语句使你可以使用比较结果控制Flash影片的播放。如下所示的语句判断X是否等于9,如果比较结果为true,则让影片跳到第15帧:
if (x == 9) {
gotoAndPlay(15);
}
if语句以if开始,其后紧跟一个比较表达式,比较表达式通常用一对括号括起来,再后面即是用大括号括起来当比较结果为true时要执行的代码。
2.else
对if语句可以进行扩展,使用else执行条件不成立(比较表达式为false)时的代码,如下所示:
if (x == 9) {
gotoAndPlay(15);
} else {
gotoAndPlay(16);
}
你也可以使用else if语句将if语句更推进一步,如下所示:
if (x == 9) {
gotoAndPlay(15);
} else if (x == 10) {
gotoAndPlay(16);
} else if (x == 11) {
gotoAndPlay(20);
} else {
gotoAndPlay(25);
}
你可以让if语句想要多长就有多长,你也可以使用else if语句对别的变量进行比较,如下所示:
if (x == 9) {
gotoAndPlay(15);
} else if (y<20) {
gotoAndPlay(16);
} else {
gotoAndPlay(25);
}
3.复合比较
你可以在一个if语句中对几个比较表达式的值进行判断,比如说你希望在x为9并且y为20时跳转到第10帧,可以使用如下所示的脚本:
if ((x == 9) && (y == 20)) {
gotoAndPlay(10);
}
逻辑与运算符&&将两个比较表达式联接在一起成为一个复合表达式,当两个表达式的值都为true时复合表达式的值才为true。每个比较表达式都需要添加独立的括号以便Flash能正确识别。在Flash的早期版本中使用and执行逻辑与运算,现在已推荐不使用。
你也可以使用逻辑或运算符||将两个比较表达式联接在一起成为一个复合表达式,只要有一个表达式的值为true,复合表达式的值就为true。如下所示:
if ((x == 7) || (y == 15)) {
gotoAndPlay(20);
}
在该脚本中,只要x为7或者y为15,或者两者都成立,结果都是跳转到第20帧。只有当两者都不成立时,才不会执行gotoAndPlay命令。在Flash的早期版本中使用or执行逻辑或运算,现在已推荐不使用。
3.4.5 循环
ActionScript中的循环要比if语句稍微复杂一点。它的循环结构与C语言中的循环结构几乎是一致的。
1.for循环结构
for结构是主要的循环结构,其样式如下所示:
for (var i = 0; i<10; i++) {
trace(i);
}
运行这段代码,随着局部变量I的改变,输出窗口中将显示数字0~9。
for结构中关键字for后面的括号中包含3个部分,它们之间用分号隔开。
第1部分声明一个局部变量,在本例中创建了一个局部变量i并将其设置为0。该部分只在循环体开始执行之前执行一次。
第2部分作为一个供测试的条件,在这里,测试i是否小于10。只要满足该条件,就会反复执行循环体。循环开始的时候i等于0,它是小于10的,所以循环得以执行。
第3部分是一个运算表达式,每完成一次循环都将执行该表达式一次。在这里,i每次递增1,然后转到第2部分对i的新值进行判断。
大括号中的部分是该循环的循环体,每执行一次循环都将执行其中的所有命令。我们来看看计算机是如何处理这个循环的。
声明变量i并将其值设为0;
判断条件i<10,结果为true,开始执行循环体;
现在i值为0,trace命令将i值发送到输出窗口,输出窗口显示0;
第1次循环结束,回到循环开始处,i在原来的基础上递增1,i值变为1;
判断条件i<10,结果为true,继续执行循环体;
trace命令将i的值1发送到输出窗口;
然后i再加1,这样循环下去直到执行完10次循环;
回到循环开始处,i在原来的基础上递增1,i值变为10;
判断条件i<10,结果为false,结束循环,开始执行for结构后面的代码。
2.其他形式的循环结构
for循环是最常用的一种循环结构,除for循环之外还有while循环和do…while循环。
while循环的例子如下所示:
i = 0;
while (i != 10) {
trace(i);
i++;
}
while循环看起来似乎要比for循环简单一些,从结构上看甚至与if语句还有一些相似。只要while后面括号中的条件成立,循环就会一直进行下去,所以在while循环体中需要有改变条件的语句,以使条件最终能够为false,完成循环,如上例中的i++。
与while循环相似的是do…while循环,如下所示:
i = 0;
do {
trace(i);
i++;
} while (i != 10);
除了测试条件的位置不同,while循环和do…while循环几乎是一样的。while循环在循环体之前测试条件,do…while循环在循环体之后测试条件,所以do…while循环至少要执行一次,而while循环有可能一次也不执行。
3.跳出循环
所有的循环结构都可以使用两个命令改变循环的执行流程,一个命令是break,另一个命令是continue。break命令终止循环,并跳到循环结构后面的语句处执行;continue命令终止本轮循环但不跳出循环,进而执行下一轮循环。
使用break和continue的例子都比较复杂,另外,还有一种特殊的for…in循环结构,在用到它们的时候我们再详细讲解。
3.4.6 函数
到现在为止,我们都是将脚本放在影片的第1帧中。如果程序相当复杂,再放在同一帧中就使脚本显得太庞大了。
函数使你可以组织需重用的代码,并放在时间轴中,例如:
function myFunction(myNum) {
var newNum = myNum+5;
return newNum;
}
函数以关键字function开头,function后面是函数名。与变量名相似,你可以指定自己的函数名,最好将函数名取得有意义一些。
函数名后面的括号容纳该函数的参数,所谓参数也是一个变量,它的值在调用该函数时予以指定。一个函数可以有若干参数,也可以没有参数。无论有没有参数,函数名后都应紧跟一对括号。
大括号中的部分是函数体,在函数体中创建了一个局部变量newNum,将myNum加5的结果设置为newNum的值。如果你将10作为参数传递给该函数,newNum的值就是15。
return命令仅用于函数中,使用return结束一个函数并返回函数值。此处,newNum是用return命令返回的函数值。
要使用函数,就需要调用它,如下所示:
var a = myFunction(7);
该语句创建一个新的局部变量a,将7作为参数调用函数myFunction,并将函数返回的结果作为变量a的值。
被调用的函数开始运行,创建一个局部变量myNum,将7作为myNum的值,然后执行函数体内的代码,使用return命令将newNum的值12返回给函数的调用者。这时,a的值变为12。
函数最大的作用体现在它可以重复使用。如下所示的3行代码产生3个不同的结果:
trace(myFunction(3));
trace(myFunction(6));
trace(myFunction(8));
运行以上代码,你将得到结果8、11和13。
使用函数还有一个好处就是可以只改变函数中的一处,从而影响所有调用该函数的命令。例如,将函数myFunction中的var newNum = myNum+5改成var newNum = myNum+7,上面3个调用该函数的命令的结果将变成10、13和15
3.4.7 点语法
ActionScript中一个很重要的概念是点语法。点语法也是很多面向对象的编程语言中用来组织对象和函数的方法。
假设你想求一个数的绝对值,Flash中有一个内置的绝对值函数,它包含在ActionScript的“对象”/“核心”/“Math”/“方法”中。要使用绝对值函数,首先要使用对象名,即Math,然后是方法名abs,它们之间用符号“.”隔开,具体表示方法如下所示:
var a = Math.abs(-7);
点语法的另一个用途是指定影片剪辑的属性。如下面的语句将影片剪辑myMC的_alpha(透明度)属性设置为50%:
myMC._alpha = 50;
你还可以在影片剪辑中使用点语法定位根(root)中的一个全局变量。如果你在主时间轴中创建了一个全局变量globelVar,而要在影片剪辑中使用这个全局变量,可以使用如下的语句:
trace(_root.globleVar);
如果你现在对对象、影片剪辑属性、层级之类的概念还不熟悉,不用着急,在以后的内容中我们将对它们进行更深入的讲解。
3.4.8 注释
我们可以在Flash的动作面板中添加注释,注释就是程序中并不参与执行的那些代码。它可以用来提醒你某些代码的作用,方便你组织和编写脚本。一个注释的例子如下所示:
// 将影片剪辑myMC的透明度设置为50%
myMC._alpha = 50;
该例的第1行是注释,注释以双斜线//开头,在//后面你可以输入任意的文本和符号,Flash会自动将注释部分用灰色标示。
上例是将注释专门放在一行中,你也可以将注释放在一行代码的后面,如下所示:
myMC._alpha = 50; // 将影片剪辑myMC的透明度设置为50%
只要使用//符号,Flash就会忽略它后面的部分。
3.5 调试脚本
无论在编写程序时有多么细心,每个程序员都避免不了要调试程序。要学好ActionScript,你就得熟练掌握调试程序的方法。在Flash MX中调试程序有3种方法:逻辑推断、向输出窗口发送信息和使用脚本调试器。
3.5.1 逻辑推断
许多程序错误其实很简单,也很容易解决,并不需要专门的调试工具。当程序出现错误时,你应对错误出现在哪里有一个大致的把握。
就算你不知道问题出在哪里,但通过细心阅读代码,你也有可能找到它。你可以思考一下,你要实现的效果是什么?现在的效果与你的设想有多大差距?是什么原因造成了这种差距?修改哪些部分有望改正这种错误?经过反复思考、修改和调试,你对程序的理解就会不断加深,你的程序也会越来越趋于正确。
没有人比你更了解你自己的程序,所以对你来说,你编写的程序最先宜采用逻辑推断的方法进行调试。还有一些错误或漏洞隐藏得比较深,这就需要借助于调试工具。
3.5.2 输出窗口
输出窗口是一个简单而实用的调试工具,在程序中可以使用trace命令将特定的信息发送到输出窗口中,这些信息可以帮助你了解代码的运行情况。
前面我们已经介绍过输出窗口,这里就不再赘述了。
3.5.3 调试器
调试器是一个更专业的调试工具,它是Flash MX中的一个窗口,通过调试器可以查看影片中的各种数据以及ActionScript代码的运行情况。
选择“控制”→“调试影片”命令,或按快捷键Ctrl+Shift+Enter,开始调试影片。与测试影片不同的是,调试影片时多了一个调试器窗口
调试器窗口中包含很多窗格,在左边的窗格中可以检查Flash影片中不同类型的对象,右边的窗格显示影片中所有的ActionScript。
在调试器窗口中可以设置断点,断点即是为某行代码添加的一个标记,当调试影片时,影片会自动在断点处停止,允许你查看当前包括变量值在内的的影片状态。使用断点可以使你逐行地执行代码,对每行代码的运行结果进行观察和分析。
初学ActionScript的时候,你可能并不需要使用调试器;但是当你成长为一名经验丰富的程序员时,你就会发现它对你是非常有用的。

 

第4章 影片播放控制

控制影片播放流程的命令有许多,如下所示:
stop:使影片停止在当前时间轴的当前帧中。
play:使影片从当前帧开始继续播放。
gotoAndStop:跳转到用帧标签或帧编号指定的某一特定帧并停止。
gotoAndPlay:跳转到用帧标签或帧编号指定的某一特定帧并继续播放。
nextFrame:使影片转到下一帧并停止。
prevFrame:使影片回到上一帧并停止。
stop命令常常用在帧动作中,以使影片停止并等待用户控制。其他命令常常用在按钮的事件处理函数中。

4.1 使影片停止
最简单的ActionScript恐怕要算stop命令了,当执行stop命令的时候,影片在当前的帧处停止播放。
你可以将stop命令放到时间轴的某一关键帧中,在stop后面需要紧跟一对括号,如下所示:
stop();
执行stop命令时,影片只是暂停在当前帧,在影片中嵌入的影片剪辑或图形元件继续播放,停止的仅仅是主时间轴中的动画。
要让影片继续播放,需要用到ActionScript的另一个命令play。play命令使影片转到下一帧并继续播放。
我们将在按钮部分介绍play命令,下面以一个例子的形式介绍stop命令的使用,其操作步骤如下:
(1)启动Flash MX,在时间轴中插入两个空白关键帧,使时间轴包含3个空白关键帧。
(2)在3个关键帧中使用文本工具分别添加字符1、2、3。
(3)选中第2帧,按F9键打开动作面板,在其中添加如下的ActionScript:
stop();
(4)按Ctrl+Enter测试影片,影片播放到第2帧即停止,你将看不到第3帧。
4.2 跳转到指定帧
另一个基本的ActionScript命令是gotoAndPlay。该命令使影片从当前帧跳转到指定的任意一帧。可以用帧编号或帧标签指定一帧,如下所示:
gotoAndPlay(9);
gotoAndPlay("myFrame");
如果影片中不止一个场景,你也可以指定要跳转到的特定场景的特定帧。如果gotoAndPlay命令中只有一个参数,Flash将认为它代表某个帧;如果有两个参数,第1个参数将作为场景名,第2个参数代表该场景中的帧。如下所示:
gotoAndPlay("myScene", 1);
它表示跳转到场景myScene的第1帧继续播放。
gotoAndPlay命令使影片跳转到某一特定帧并从该帧开始继续播放,如果要使影片跳转到某一特定帧并在该帧位置停止,就应该使用gotoAndStop命令。它的使用方法与gotoAndPlay命令相似,仅仅是跳转帧后执行的动作不同罢了。
还有两个实现跳转帧动作的命令,它们是nextFrame和prevFrame。nextFrame命令使影片从当前位置转到下一帧并停止,prevFrame命令使影片从当前位置转到上一帧(即回退一帧)并停止。它们后面都必须使用括号。
要了解这些命令究竟如何使用,最好的方法就是使用按钮,下面我们就来看看如何创建按钮。
4.2.1 创建按钮
要创建按钮,可以选择“插入”→“新建元件”命令或按快捷键Ctrl+F8,你将看到一个“创建新元件”对话框,在该对话框中你可以在影片剪辑、按钮和图形这3种类型中选择要创建元件的类型。
选择按钮类型,单击“确定”按钮,Flash窗口将由主场景切换到按钮元件的编辑场景。按钮元件的时间轴中有4个帧,分别是弹起(Up)、指针经过(Over)、按下(Down)、和点击(Hit),它们代表了按钮的3种状态和热区(热区的形状代表了按钮能在什么范围内感应到鼠标的动作)。
如果你在按钮的第1帧中放置一个图形,而在其他3个帧中不放置任何东西,那么该按钮的3种状态和热区将是一样的。
要使按钮显示不同的状态,就需要在它的不同关键帧中创建不同的图形或影片剪辑。
完成对按钮的创建后,可以单击舞台上方的场景名“场景1”回到主场景。
按F1或Ctrl+L打开库面板,你将看到库中增加了一个按钮,用鼠标将它拖到舞台中。
4.2.2 为按钮添加脚本
要为按钮添加脚本,首先得选中该按钮,然后按F9键打开动作面板。你也可以在该按钮上单击鼠标右键,在弹出的快捷菜单中选择“动作”命令,这样也可以打开按钮的动作面板。
在专家模式下输入如下脚本:
on (release) {
trace("You are cliking me!");
}
按钮的脚本有特殊的语法,即必须以关键字on开头,以on开头的代码是一种事件处理函数,即当特定事件发生时要执行的代码。在这里,特定事件就是release(松开鼠标),它是按钮最常用的事件。
按钮事件还有press、releaseOutside、rollOver、rollOut、dragOver、dragOut以及keyPress等。press是按下鼠标事件,它在release事件之前发生,releaseOutside是在按钮上按下鼠标,并且在按钮外松开鼠标的事件,rollOver是鼠标指针移到按钮所在热区的事件,rollOut是鼠标从按钮热区移出的事件,dragOver是在鼠标指针位于按钮上方并已按下按钮的情况下,滑出按钮再滑回按钮的事件,dragOut是当鼠标指针位于按钮内部,按下按钮然后滚动出按钮区域的事件,keyPress是按钮响应在键盘上按下某些键时的事件。
某种事件的发生,会触发相应事件处理函数开始运行,上例中使用trace语句将事件信息发送到输出窗口中,使你可以更好地了解具体按钮事件的含义。
4.3 练习:演示文档
用Flash可以实现演示文档的功能,演示文档相当于我们常说的幻灯片,它可以进行逐页展示。如果不使用脚本,Flash动画会很快地播放每一帧,要用Flash制作演示文档就得对Flash添加控制命令。
我们用脚本使每一帧停止,要跳转到别的帧,就需要使用按钮。
制作演示文档的操作步骤如下:
(1)启动Flash MX,编辑前5帧。
(2)在文档中创建5个按钮,从库面板中可以看到它们。
(3)打开主时间轴第1帧的动作面板,其中添加了如下语句:
stop();
影片播放时,会停止在第一帧上。
(4)为图层2的第1帧和第5帧分别添加帧标签begin和end,
(5)选中第1帧中的“开始”按钮,打开其动作面板,在其中添加如下语句:
on (release) {
nextFrame();
}
单击“开始”按钮,停止在第1帧的影片会跳转到第2帧并停止。
(6)分别在第2~4帧的相同位置添加按钮“首页”、“上一页”、“下一页”、“末页”。由于第5帧后面没有别的帧,所以只添加“上一页”和“首页”两个按钮。
(7)为所有“首页”按钮添加脚本:
on (release) {
gotoAndStop("begin");
}
单击“首页”按钮,影片将跳转到帧标签为begin的那一帧并停止,即第1帧。这里也可以用1替代"begin"。
(8)为所有“上一页”按钮添加脚本:
on (release) {
prevFrame();
}
单击“上一页”按钮,影片将从当前帧跳转到前一帧并停止。
(9)为所有“下一页”按钮添加脚本:
on (release) {
nextFrame();
}
单击“下一页”按钮,影片将从当前帧跳转到下一帧并停止。
(10)为所有“末页”按钮添加脚本:
on (release) {
gotoAndStop("end");
}
单击“末页”按钮,影片将从当前帧跳转到帧标签为end的那一帧并停止,在此处也即是第5帧。
(11)按Ctrl+Enter键测试一下影片,单击各个按钮试一下效果。这些添加了ActionScript的按钮是不是变得非常听话?

 

第5章 控制影片剪辑

影片剪辑是Flash中最重要的一种元件,对影片剪辑的控制是ActionScript的最重要功能之一。从根本上说,Flash的许多复杂动画效果和交互功能都与影片剪辑的运用密不可分。
使用点语法或方括号可以定位影片剪辑。使用方括号时可以使用由变量表示的影片剪辑实例名,这是它相对于点语法的优点。
可以用脚本控制影片剪辑的各种动作,也可以在影片剪辑的事件处理函数中控制主时间轴和别的影片剪辑。影片剪辑最重要的两个事件是load和enterFrame。

5.1 控制影片剪辑的播放动作
设想一个Flash动画,它的主场景中只有一个帧,舞台中只有一个影片剪辑,影片剪辑中并没有ActionScript。如何才能控制影片剪辑的播放动作呢?
要控制一个影片剪辑,首先应该为影片剪辑命名。容易混淆的是,库面板中的影片剪辑本身有一个名称,这里要命名的是场景中影片剪辑实例的名称。它们可以相同,也可以不相同。如果你在场景中创建了同样的影片剪辑的多个实例,那么就需要将每个实例以不同的名称命名,才能用ActionScript对每一个实例进行控制。如果不需要对影片剪辑进行控制,也就不需要为影片剪辑的实例命名。
从本例文件中,你将看到库面板中只有一个影片剪辑rollmc,场景中创建了一个rollmc的实例。你还可以再从库中拖出若干个rollmc的实例将它们放置到场景中。
选中场景中影片剪辑rollmc的实例,打开属性面板,可以看到它被命名为roll,你同时可以看到该影片剪辑原来的名字rollmc。你也可以为它指定别的名称,也可以是rollmc,Flash并不会混淆它们之间的区别。 实例名称可以在程序中用来指代该影片剪辑实例,如果要控制该实例,就需要在脚本中使用该名称。下面,我们就来看看如何通过脚本控制影片剪辑实例roll。
分别选中场景中的4个按钮,打开它们的动作面板,查看其中的代码。
“STOP”按钮:
on (release) {
roll.stop();
}
单击“STOP”按钮使roll实例停止播放。
“PLAY”按钮:
on (release) {
roll.play();
}
单击“PLAY”按钮使roll实例继续播放。
“PREV”按钮:
on (release) {
roll.prevFrame();
}
单击“PREV”按钮使roll实例回退一帧并停止。
“NEXT”按钮:
on (release) {
roll.nextFrame();
}
单击“NEXT”按钮使roll实例播放一帧并停止。
按Ctrl+Enter键测试影片,如图5-2所示。一开始影片剪辑自动播放。单击不同的按钮看看影片剪辑是否执行相应的动作。
除了这几种命令,你还可以使用gotoAndStop或gotoAndPlay命令控制影片剪辑跳转到具体的帧,但是在命令前面都需要指定影片剪辑的实例名称。
这种方法是在影片剪辑实例所在的层级中控制影片剪辑,如果是在影片剪辑内部,要控制它自身的播放,就可以直接使用stop、play等命令,而不需要指定实例名称。如果你在影片剪辑内部的时间轴中使用了名称roll,Flash会在影片剪辑内部的时间轴中寻找该实例。
5.2 定位影片剪辑
我们已经了解了如何使用最简单的方法定位一个影片剪辑,即使用影片剪辑的实例名,后面紧跟一个点记号“.”,然后是你想要影片剪辑执行的命令。
还有许多方法可以定位影片剪辑。首先,我们来看看如何定位Flash影片中不同层级的对象。
Flash影片中最基本的目标层级就是它的主时间轴。可以用关键字_root来表示和定位主时间轴。
例如,你要向主时间轴发送一个gotoAndStop命令,可以使用如下所示的语句:
_root.gotoAndStop(9);
如果这个命令是包含在主时间轴的某一帧上的,则可以省略目标_root。如果这个命令是包含在主时间轴上某个影片剪辑中,需要由影片剪辑来控制它上一级的主时间轴,_root就很有必要了。
通常,要定位包含某一对象的上一级对象,可以使用关键字_parent。所以,如果一个影片剪辑是包含在主时间轴中,在影片剪辑中使用_parent和_root的效果是一样的。如果影片剪辑与主时间轴相差两个层级,即当影片剪辑包含在另一个位于主时间轴中的影片剪辑中,这时在该影片剪辑中使用_parent指代的是它上一级的影片剪辑,而_root是指它上两级的主时间轴。在主时间轴中不能使用_parent,因为主时间轴没有上一级。
可以用数字来方便地说明这种层级关系。主时间轴,它始终是最初级,作为层级0。主时间轴中的一个影片剪辑处于层级1。如果影片剪辑中包含另一个影片剪辑,它处于层级2。对层级2上的影片剪辑来说,_parent指代的就是层级1上的影片剪辑,而不管对哪一级来说,_root始终指代层级0上的主时间轴。
除了用点记号连接_root和实例名,还可以使用方括号表示_root上的对象。对上例中的按钮“STOP”来说,如下所示的3种方法作用是一样的:
rool.stop();
_root.roll.stop();
_root["roll"].stop();
还有一个关键字this,它代表脚本当前所在的层级。如果脚本位于主时间轴中,this即指代主时间轴;如果脚本位于影片剪辑中,this即指代该影片剪辑。所以以上语句还可以用以下两种方式表示:
this.roll.stop();
this["roll"].stop();
使用_root和this时还可以用变量来定位影片剪辑,如下所示:
var mcInsName = "roll";
_root[mcInsName].stop();
今后我们会遇到这种情况,即有roll0~rool99共100个影片剪辑实例,可以使用下面的语句来控制它们:
on (release) {
for (var i = 0; i<100; i++) {
_root["roll"+i].stop();
}
}
多数情况下我们习惯使用_root,但在某些情况下使用this比_root更简便。如要在某个影片剪辑中定位包含 在此影片剪辑中的另一影片剪辑childMC,就可以直接使用this.childMC。
5.3 为影片剪辑添加脚本
现在你已经知道如何向帧和按钮中添加脚本,下面需要知道如何向影片剪辑中添加脚本。
要为影片剪辑添加脚本,首先要选中影片剪辑,再打开它对应的动作面板,然后在其中输入脚本。影片剪辑脚本和按钮的脚本类似,它们都使用事件处理函数,与按钮的on关键字不同,影片剪辑使用onClipEvent关键字。当某种影片剪辑事件发生时,就会触发相应的事件处理函数。
影片剪辑最重要的两种事件是load和enterFrame。
load事件在影片剪辑完全加载到内存中时发生。在每次播放Flash影片时,每个影片剪辑的load事件只发生一次。
在主时间轴停止播放时,影片中的影片剪辑并不会停止播放,这个特性决定了影片剪辑的另一个事件enterFrame的重要性。enterFrame事件在影片每次播放到影片剪辑所在帧时发生。如果主时间轴中只有一帧,且不论它是否在该帧停止,该帧中的影片剪辑都会不断触发enterFrame事件,且触发的频率与Flash影片的帧频一致。
影片剪辑事件的使用方法如下所示:
onClipEvent (load) {
var i = 0;
}
onClipEvent (enterFrame) {
trace(i);
i++;
}
当影片剪辑的load事件发生时,将变量i设置为0。当影片剪辑的enterFrame事件发生时,向输出窗口中发送i的值,然后将i加1。输出窗口中会从0开始输出以1递增的数字序列,直到影片被关闭为止。
为了熟悉影片剪辑事件处理函数的用法,我们来为影片剪辑编写一段简单的脚本,使影片剪辑逆序播放,
我们将从影片剪辑的最后一帧处开始播放,使用prevFrame命令使影片剪辑每次后退一帧。
本例文件场景中有一个影片剪辑元件rollmc,查看一下它的属性面板,并没有为其实例命名,这是因为我们要直接在影片剪辑的动作面板中添加脚本,并不需要用到实例名称。
选中影片剪辑rollmc,此时动作面板的标题栏中应为“动作-影片剪辑”。打开动作面板,其中添加了如下ActionScript:
onClipEvent (load) {
gotoAndStop(40);
}
onClipEvent (enterFrame) {
prevFrame();
}
在事件处理函数onClipEvent (load)中,令Flash影片的播放头转到影片剪辑的第40帧(即最后一帧)。这个事件处理函数只在影片剪辑被加载完成时执行1次。第2个事件处理函数onClipEvent (enterFrame)每播放1帧就执行1次,使影片剪辑回退1帧。
按Ctrl+Enter键测试影片,你将看到齿轮以与上例相反的方向转动,直到影片剪辑的时间轴回到第1帧,prevFrame命令不起作用,影片剪辑停止播放。要让它连续不断的播放,可以在影片剪辑元件rollmc的时间轴第1帧的动作面板中添加如下语句:
gotoAndStop(40);
5.4 用影片剪辑控制别的影片剪辑
一个影片剪辑可以控制别的影片剪辑。综合使用_root或_parent关键字、点符号和影片剪辑实例名称可以将命令发送给另一个影片剪辑实例。例如,在主时间轴上的影片剪辑实例roll1中添加如下脚本以控制同在主时间轴上的影片剪辑实例roll2回退1帧:
_root.roll2.prevFrame();
或者使用方括号表示如下:
_root["roll2"].prevFrame();
如果两个影片剪辑不同在主时间轴上,而是同在别的层级上,可以使用_parent关键字。如果它们不同在一个层级上,也只需要使用点符号逐级标明所在的路径即可。
下面综合运用以上知识实现以影片剪辑控制另一个剪辑的播放动作。
(1)打开本例文件。分别查看场景中的每一层。按Ctrl+L打开库面板。库面板中有三个影片剪辑元件,分别是hour、minute和second。
(2)分别双击每个影片剪辑元件,查看它们的时间轴。
(3)second元件的的时间轴共60帧,secondhand图形元件顺时针旋转1周。在第1帧中添加了如下ActionScript:
stop();
在最后1帧中添加了如下ActionScript:
_root[target].nextFrame();
gotoAndStop(1);
(4)minute元件的的时间轴共60帧,minutehand图形元件顺时针旋转1周。在第1帧中添加了如下ActionScript:
stop();
在最后1帧中添加了如下ActionScript:
_root[target].nextFrame();
gotoAndStop(1);
(5)hour元件的的时间轴共12帧,hourhand图形元件顺时针旋转1周。在第1帧中添加了如下ActionScript:
stop();
(6)回到主场景,在属性面板中为hour影片剪辑和minute影片剪辑指定了与元件名称相同的实例名称。
(7)选中second元件实例,打开其动作面板,其中添加了如下ActionScript:
onClipEvent (load) {
target = "minute";
}
onClipEvent (enterFrame) {
nextFrame();
}
(8)选中minute元件实例,打开其动作面板,其中添加了如下ActionScript:
onClipEvent (load) {
target = "hour";
}
以上脚本的原理是:使每个影片剪辑都在各自的第1帧停止。在second的enterFrame事件中令其自身移到下一帧。直到second元件转动完一周,到达最后一帧,使用_root[target].nextFrame();命令将target所指目标后移1帧,这里的target是在second影片剪辑实例的load事件中定义的,也就是minute。同样,直到minute元件转动完一周到达最后1帧,使用_root[target].nextFrame();命令将target所指目标后移1帧,这里的target是在minute影片剪辑实例的load事件中定义的,也就是hour。
由于影片剪辑的转动是由nextFrame命令实现的,所以在每个元件内部时间轴的最后1帧中添加了跳转到第1帧的语句,避免停止在最后1帧上。
上面的ActionScript主要有两种,一种是在影片剪辑内部时间轴上的帧脚本,另一种是在主时间轴中的影片剪辑脚本。我们使用一个全局变量target记录影片剪辑实例名称,这个动作是在影片剪辑的事件处理函数中完成的,然后将这个全局变量应用到影片剪辑内部的帧脚本中。从这里也可以看到,影片剪辑动作和影片剪辑内部的帧动作是可以进行通信的,全局变量在它们之间有效,但在两个影片剪辑之间就变得无效,所以我们可以在两个影片剪辑中同时使用target而互不影响。
(9)按Ctrl+Enter测试影片

 

第6章 影片剪辑属性 

通过调整影片剪辑的各种属性可以改变影片剪辑的位置和显示状态。_x和_y属性代表影片剪辑在场景中的水平坐标和垂直坐标。_xscale和_width属性决定影片剪辑在水平方向上的显示宽度,_yscale和_height属性决定影片剪辑在垂直方向上的显示高度。使用_rotation属性可以旋转影片剪辑。_alpha属性代表影片剪辑的透明度,_visible属性决定影片剪辑是否可见。使用关键字_xmouse和_ymouse可以获取鼠标光标在屏幕中的坐标位置。

6.1 坐标
Flash场景中的每个对象都有它的坐标,坐标值以像素为单位。Flash场景的左上角为坐标原点,它的坐标位置为0,0,前一个0表示水平坐标,后一个0表示垂直坐标。Flash默认的场景大小为550×400像素,即场景右下角的坐标为550,400,它表示距坐标原点的水平距离为550,垂直距离为400。
场景中的每一点都可以用坐标表示
习惯地,水平坐标用x表示,垂直坐标用y表示。在Flash中,分别用_x和_y表示x坐标值属性和y坐标值属性。例如,要在主时间轴上表示场景中的影片剪辑myMC的位置属性,可以使用下面的方法:
myMC._x
myMC._y
如果是在myMC自身的脚本中表示它的坐标,也以使用如下的方法:
_x;
_y;
或:
this._x;
this._y;
在属性面板和信息面板中都有可以查看和更改对象的位置。选择“窗口”→“信息”命令或按快捷键Ctrl+I都可以打开信息面板
信息面板中显示了当前所选图形或影片剪辑的大小、坐标位置、颜色以及鼠标位置等。图6-2中信息面板右边的两个数值框X和Y代表了所选对象的水平坐标和垂直坐标。面板中的 图标表示坐标位置是以所选对象的左上角为基准还是以中心为基本。当前左上角方块呈黑色显示,表示坐标位置以对象左上角为基准,如果中心方块呈黑色显示,表示坐标位置以对象中心为基准。
通过更改_x和_y属性可以在影片播放时改变影片剪辑的位置。如可以为影片剪辑编写如下的事件处理函数:
onClipEvent (enterFrame) {
_x += 5;
_y += 5;
}
该事件处理函数使影片剪辑在每次enterFrame事件中向右和向下移动5像素的位置。
6.2 鼠标位置
你不但可以获得影片中影片剪辑的坐标位置,还可以获得鼠标位置,即鼠标光标在影片中的坐标位置。
表示鼠标光标的坐标属性的关键字是_xmouse和_ymouse,其中,_xmouse代表光标的水平坐标位置,_ymouse代表光标的垂直坐标位置。
需要说明的是,如果这两个关键字用在主时间轴中,则它们表示鼠标光标相对于主场景的坐标位置;如果这两个关键字用在影片剪辑中,则它们表示鼠标光标相对于该影片剪辑的坐标位置。_xmouse和_ymouse属性都是从对象的坐标原点开始计算的,即在主时间轴中代表光标与左上角之间的距离;在影片剪辑中代表光标与影片剪辑中心之间的距离。
多数情况下,你需要用到鼠标光标在主场景中的位置,所以可以使用_root._xmouse和_root._ymouse表示。
你可以使用下面的代码让影片剪辑保持与鼠标位置相同的坐标值:
onClipEvent (enterFrame) {
_x = _root._xmouse;
_y = _root._ymouse;
}
Flash不能获得超出影片播放边界的鼠标位置。这里的边界并不是指影片中设置的场景大小。如将场景大小设置为550×400,在正常播放时能获得的鼠标位置即在(0,0)~(550,400)之间;如果缩放播放窗口,将视当前播放窗口的大小而定;如果进行全屏播放,则与显示器的像素尺寸有关。
6.3 旋转方向
影片剪辑的另一个属性是_rotation。
_rotation属性代表影片剪辑的旋转方向,它是一个角度值,介于-180°~180°之间,可以是整数和浮点数。
_rotation的值始终保持在-180°~180°之间,如果将它的值设置在这个范围之外,系统会自动将其转换为这个范围之间的值。例如,将_rotation的值设置为181°,系统会将它转换为-179°;将_rotation的值设置为-181°,系统会将它转换为179°。
如使用下面的语句实现影片剪辑的连续转动:
onClipEvent (enterFrame) {
_rotation += 10;
}
不用担心_rotation会超出它的范围,系统会自动将它的值转换到-180°~180°之间,并不会影响到影片剪辑转动的连贯性。
6.4 可见性
影片剪辑的另一个属性是_visible,即可见性。_visible属性使用布尔值,即要么为true(1),要么为false(0)。为true表示影片剪辑可见,即显示影片剪辑;为false表示影片剪辑不可见,隐藏影片剪辑。
例如要隐藏影片剪辑myMC:
myMC._visible = false;
6.5 透明度
_alpha(透明度)是区别于_visible的另一个属性,_alpha决定了影片剪辑的透明程度,它的范围在0~100之间,0代表完全透明,100表示不透明。
例如要将影片剪辑myMC的透明度设为50%:
myMC._alpha = 50;
_alpha属性代表了第4种颜色通道,即所谓的alpha通道。前3种颜色通道分别为red(红)、green(绿)、blue(蓝),也就是我们说的三原色通道,通常也简称R、G、B通道。前3种颜色通道决定像素的颜色成份,alpha通道决定像素的透明程度。在计算机中,每种颜色通道都用8 bit(位)来存储,所以如果一幅图像是32位的,它就有所有这4个通道;如果一幅图像是24位的,则它就只有R、G、B这3个通道。
也可以在脚本中设置按钮的_alpha属性。特别指出,将按钮的_alpha属性设置为0,虽然按钮不可见,但是它的热区同样存在,仍然可以对它进行单击等操作;如果要将按钮变为不可用,可以将其_visible属性设置为false。
6.6 缩放属性
影片剪辑的缩放属性包括横向缩放_xscale和纵向缩放_yscale。
_xscale和_yscale的值代表了相对于库中原影片剪辑的横向尺寸width和纵向尺寸height的百分比,而与场景中影片剪辑实例的尺寸无关。如库中影片剪辑元件的横向宽度为150,在场景中将它的实例宽度调整为10,在脚本中将_xscale设置为50,则它在影片播放时显示的横向宽度将是150的50%,即75,而不是50像素或10的50%。
当_xscale和_yscale是0~100之间的数时,缩小原影片剪辑;当_xscale和_yscale是大于100的数时,放大原影片剪辑;当_xscale或_yscale为负时,将在缩放的基础上水平或垂直翻转原影片剪辑。
本例文件包含了一个矩形的影片剪辑和一幅图片,并将矩形所在图层作为遮罩层
在矩形影片剪辑的动作面板中添加如下ActionScript:
onClipEvent (load) {
xs = _width;
ys = _height;
}
onClipEvent (enterFrame) {
_xscale = 100*(_root._xmouse-_x)/(xs/2);
_yscale = 100*(_root._ymouse-_y)/(ys/2);
}
在load事件中,用变量xs和ys取得影片剪辑初始状态下的宽度和高度值。在enterFrame事件中,计算鼠标位置与矩形影片剪辑中心的距离,算出它与矩形宽度和高度值的比值,然后作为_xscale和_yscale的值。该动画实现移动鼠标位置以改变遮罩效果
6.7 尺寸属性
上面例子中我们用到了影片剪辑的另两个属性:_width和_height。与_xscale和_yscale属性不同,_width和_height代表影片剪辑的绝对宽度和高度,而不是相对比例。
同样可以使用_width和_height调整影片剪辑的尺寸大小,如上例中的ActionScript也可写成如下所示:
onClipEvent (enterFrame) {
_width = Math.abs(_root._xmouse-_x)*2;
_height = Math.abs(_root._ymouse-_y)*2;
}
Math.abs是一个内置函数,用以计算一个数或表达式的绝对值。因为与缩放属性不同,_width和_height的值不能为负,所以这时使用绝对值函数始终给出一个不为负的值。
此处用更简洁的脚本实现了与上例相同的效果。
6.8 练习:使用影片剪辑的各种属性
该动画包含一支球杆影片剪辑stick,一个母球影片剪辑ball。在屏幕中移动鼠标,球杆会跟随鼠标转动,这是利用鼠标位置控制球杆的_rotation属性。球杆的影片剪辑中添加了一个隐性按钮(只有最后1帧作为热区,前面3帧都有为空,所以是不可见的),当单击球杆时,控制球杆影片剪辑向后播放,作回拉动作,再出杆击球。当球杆前端回到球的轮廓位置时,用球杆影片剪辑控制母球影片剪辑,将母球击出,然后将其自身的_visible属性设置为false,隐藏球杆。通过调整母球的_x和_y属性,实现母球的滚动、反弹等动作。在母球滚动时,分析母球位置以判断母球是否落袋,如果母球落袋,则使用trace语句给出提示“bad”,将母球重新置于初始位置。当母球停止滚动时,将球杆的_visible属性重新设置为true,并将球杆的位置设置为与母球相同,等待下一次击球。
球杆stick影片剪辑元件:
(1)在stick影片剪辑元件第1帧的帧动作面板中添加如下语句:
stop();
(2)在第2、10、12帧中添加动作,使球杆作回拉——出杆运动。第12帧时的球杆前端应与中心保持相当于母球半径长度即7.5像素的距离,在此帧时将母球击出。
(3)在第12帧的动作面板中添加如下ActionScript:
_root.motherball.v = 20;
_root.motherball.dir = _root.stick._rotation;
上面的语句为motherball实例传送两个参数值v和dir,v代表了母球的运动速度,dir代表了母球的运动方向,它的方向与球杆的旋转方向相同。
(4)在第13~20帧添加过渡,使球杆击球后在场景中保留一段时间。
(5)在第20帧的动作面板中添加如下ActionScript:
_visible = false;
该语句将球杆自身隐藏。
(6)将第1帧中的球杆转换成按钮,选中该按钮,在动作面板中添加如下ActionScript:
on (release) {
play();
}
单击该钮,球杆往后播放,作击球动作。
球杆影片剪辑实例:
在主场景中将球杆和母球放在左边,将它们的中心对齐。为球杆影片剪辑添加如下ActionScript:
onClipEvent (load) {
_x = _root.motherball._x;
_y = _root.motherball._y;
}
onClipEvent (mouseMove) {
xsm = _root._xmouse-_x;
ysm = _root._ymouse-_y;
if (xsm<0) {
_rotation = Math.atan(ysm/xsm)*(180/Math.PI);
} else {
_rotation = Math.atan(ysm/xsm)*(180/Math.PI)+180;
}
}
Math.atan是Flash的内置函数,用它求一个数或表达式的反正切值。Math.PI是Flash的内置常数,代表圆周率。使用Math.atan计算出的反正切值的单位是弧度,而_rotation属性的单位是角度,所以要将其乘以(180/Math.PI)以实现弧度到角度的转换。
在球杆影片剪辑的mouseMove事件中,根据鼠标位置调整_rotation属性的值,使影片剪辑跟随鼠标转动,这也是鼠标跟随动画中的一种。
母球影片剪辑实例:
在母球影片剪辑实例的动作面板中添加如下ActionScript:
onClipEvent (load) {
v = 0; //初速度
dir = ""; //运动方向
vx = 0; //x方向分速度
vy = 0; //y方向分速度
slow = 0; //加速度
x0 = _x; //初始x位置
y0 = _y; //初始y位置
}
onClipEvent (enterFrame) {
//母球运动中
if ((dir != "") && (slow<100)) {
//母球落袋
if (((_x<60) && (_y<85)) || ((_x>440) && (_y<85)) || ((_x<60) && (_y>265)) || ((_x>440) && (_y>265))) {
_visible = false;
trace("Bad!");
dir = "";
v = 0;
vx = 0;
vy = 0;
slow = 0;
_x = x0;
_y = y0;
_visible = true;
//在母球位置显示球杆
_root.stick._visible = true;
_root.stick.gotoAndStop(1);
_root.stick._x = x0;
_root.stick._y = y0;
}
//撞击球桌左边界
if (_x<60) {
_x = 60;
dir = -(180+dir);
}
//撞击球桌右边界
if (_x>440) {
_x = 440;
dir = 180-dir;
}
//撞击球桌上边界
if (_y<85) {
_y = 85;
dir = -dir;
}
//撞击球桌下边界
if (_y>265) {
_y = 265;
dir = -dir;
}
//调整母球位置和速度
v0 = v*(100-slow)/100;
vx = v0*Math.cos((dir)/(180/Math.PI));
vy = v0*Math.sin((dir)/(180/Math.PI));
_x += vx;
_y += vy;
slow++;
}
//母球减速完毕
if (slow == 100) {
//在母球位置显示球杆
_root.stick._x = _root.motherball._x;
_root.stick._y = _root.motherball._y;
_root.stick._visible = true;
//重置变量
dir = "";
v = 0;
vx = 0;
vy = 0;
slow = 0;
}
}

 

 

第7章 影片剪辑方法

控制影片剪辑的方法很多,在ActionScript中最常用和最有用的命令是duplicateMovieClip和attachMovie,它们用于复制和附加影片剪辑,这两个命令可以实现许多效果,如下雪、棋类、射击游戏等。
使用hitTest方法可以代替按钮实现人机交互,从这里也可以看出影片剪辑有多么强大的功能。
startDrag和stopDrag用于对影片剪辑进行拖动,它们可以灵活地实现许多有趣的效果。

7.1 复制和附加影片剪辑
使用ActionScript的一大理由便是它可以极大地提高工作效率,达到事半功倍的效果。本章要介绍的两个命令duplicateMovieClip和attachMovie便是其中的典范。
7.1.1 Array对象
Array对象(动作面板的“对象”/“核心”目录)即数组,它用来记录成组的相关或相似变量。数组中的单个变量称为元素,数组中的每个元素对应一个索引,访问元素需要使用索引,索引需要用方括号括起来。
如下所示的ActionScript创建一个空的数组:
myArray = new Array();
如下所示的ActionScript创建一个确定值的数组并在输出窗口中显示每个元素的值:
weekDay = new Array("SUN", "MON", "TUE", "WED", "TUR", "FRI", "SAT");
for (var i = 0; i<7; i++) {
trace(weekDay[i]);
}
数组中还可以嵌套数组,即构成多维数组,如下所示:
polyArray = new Array();
for (var i = 0; i<3; i++) {
polyArray[i] = new Array(i*3+1, i*3+2, i*3+3, i*3+4);
trace(polyArray[i][0]+" "+polyArray[i][1]+" "+polyArray[i][2]+" "+polyArray[i][3]);
}
输出窗口中将显示:
1 2 3 4
4 5 6 7
7 8 9 10
7.1.2 复制影片剪辑
duplicateMovieClip动作(动作面板的“动作”/“影片剪辑控制”目录)和MovieClip对象(动作面板的“对象”/“影片”目录)中的duplicateMovieClip方法都用于在影片播放时创建影片剪辑的实例,也即复制场景中的父影片剪辑以产生新的影片剪辑。它们和后面要介绍的attachMovie方法对于要在影片中重复产生较多相同图形或动画对象时非常有用,如棋类游戏、射击游戏、鼠标跟随、下雪等特效动画。
要使用duplicateMovieClip动作和MovieClip.duplicateMovieClip方法,首先需要在场景中创建用来复制的父影片剪辑,并且在属性面板中为该父影片剪辑实例命名,该影片剪辑实例名称将作为duplicateMovieClip的参数之一。
在帧动作中使用duplicateMovieClip动作的方法如下所示:
duplicateMovieClip("parentMC", "childMC", 10);
其中,第1个参数parentMC是父影片剪辑的唯一标识符,第2个参数childMC是复制产生的新影片剪辑实例的唯一名称,第3个参数10是新影片剪辑的深度级别(level)。深度级别的概念与层类似,较高深度级别中的图形会遮挡住较低深度级别中的图形,影片剪辑所在的深度级别越高就越贴近我们的视线。在同一个深度级别中只能有一个影片剪辑实例,如果在同一深度级别中添加多于一个影片剪辑实例,新的影片剪辑实例将替换掉旧的影片剪辑实例。
复制产生的影片剪辑实例与父影片剪辑实例的位置是重叠在一起的,所以一般还需要调整新影片剪辑实例的坐标等属性,以使其按照需要显示,如下所示:
_root.parentMC._visible = false;
duplicateMovieClip("parentMC", "childMC", 10);
_root.childMC._x = 275;
_root.childMC._y = 200;
运行以上脚本,屏幕中只能看到新影片剪辑实例,而父影片剪辑实例不见了。从这里也可以看出,父影片剪辑实例的属性并不会影响到复制产生的新实例。
通常情况下,可以用与下面类似的方法复制多个影片剪辑实例:
_root.parentMC._visible = false;
n = 50;
for (i=0; i<n; i++) {
duplicateMovieClip("parentMC", "childMC"+i, 10+i);
_root["childMC"+i]._x = 25+10*i;
_root["childMC"+i]._y = 8*i;
}
在父影片剪辑中使用MovieClip.duplicateMovieClip方法如下所示:
onClipEvent (enterFrame) {
this.duplicateMovieClip("childMC", 10);
_root.childMC._x += 150;
}
它比duplicateMovieClip动作少了第1个参数,即不需要父剪辑名称。如果以上脚本不是在父剪辑而是在别的影片剪辑中,只需要将this换成父剪辑的实例名称即可。
7.1.3 附加影片剪辑
attachMovie方法也是在影片播放时创建影片剪辑的实例,它与duplicateMovieClip不同的是,attachMovie方法不需要使用父影片剪辑,而是将库中影片剪辑的实例附加到场景中。
要使用attachMovie方法,首先需要在库面板中为要附加到场景中的影片剪辑添加链接。为影片剪辑添加链接的方法如下:
(1)在库面板中要添加链接的影片剪辑上单击鼠标右键,在弹出的快捷菜单中选择“链接”命令。
(2)系统弹出“链接属性”对话框,
(3)在“链接:”后选中“为动作脚本导出”复选框,“为运行时共享导入”复选框自动变为选中状态,“标识符”文本框变为可用,并将影片剪辑的元件名称作为默认的链接标识符
(4)单击“确定”按钮,添加链接后的库面板
为影片剪辑添加链接后,就可以在动作脚本中调用它,如下所示:
attachMovie("blackchess", "chess1", 100);
第1个参数即在库面板中添加的链接名称,第2个参数和第3个参数的意义和使用方法与duplicateMovieClip中相同位置的参数类似。
在使用attachMovie方法将影片剪辑实例附加到场景中后,该实例将默认出现在场景左上角,即坐标原点的位置,所以仍然需要调整它的位置等属性。
7.1.4 删除影片剪辑
通过以上方法创建的影片剪辑实例都可以使用removeMovieClip动作(动作面板的“动作”/“影片剪辑控制”目录)或MovieClip对象的removeMovieClip方法删除,如下所示:
n = 50;
for (i=0; i<n; i++) {
removeMovieClip(_root["childMC"+i]);
}
7.2 练习:动态添加影片剪辑
本例是一个运用了duplicateMovieClip和attachMovie命令的鼠标跟随特效动画,
本例使用attachMovie命令将鱼附加到场景中的,使用duplicateMovieClip命令复制荷花影片剪辑以调整它的深度级别,使其保持在鱼的上面。
该文件只有两层,图层1用来处理鱼,图层2用来处理荷花。场景中只添加了荷花影片剪辑,它的实例名称与元件名称同为picMC。在库面板中为鱼的身体元件设置了链接,链接标识符与元件名称相同。
(1)在图层1的第1帧添加如下ActionScript:
unit = 20; //鱼的分段数:20
v0 = 12; //鱼的游动速度
v1 = 2/3; //鱼身紧骤程度
v2 = 3; //鱼身大小递减速度
var x = new Array(); //创建横坐标数组
var y = new Array(); //创建纵坐标数组
for (i=1; i<=unit; i++) {
if (i == 1) {
attachMovie("head", "fish"+i, unit+1-i); //在第1节附加鱼头
} else if ((i == 4) or (i == 13)) {
attachMovie("fin", "fish"+i, unit+1-i); //在第4和13节附加鱼鳍
} else {
attachMovie("body", "fish"+i, unit+1-i); //在其他节附加鱼身
}
_root["fish"+i]._xscale = 50-v2*(i-1); //宽度递减
_root["fish"+i]._yscale = 60-v2*(i-1); //高度递减
_root["fish"+i]._alpha = 100-(100/unit)*i; //透明度递减
}
(2)在图层1的第2帧添加如下ActionScript:
x[0] += (_xmouse-x[0])/v0;
y[0] += (_ymouse-y[0])/v0;
for (i=1; i<=unit; i++) {
x[i] = x[i]+(x[i-1]-x[i])*v1;
y[i] = y[i]+(y[i-1]-y[i])*v1;
} //为数组元素赋值
for (i=1; i<=unit; i++) {
_root["fish"+i]._x = (x[i-1]+x[i])/2;
_root["fish"+i]._y = (y[i-1]+y[i])/2;
_root["fish"+i]._rotation = 90+180/Math.PI*Math.atan2((y[i]-y[i-1]), (x[i]-x[i-1]));
} //确定鱼身各节坐标位置和旋转方向
(3)在图层1的第3帧添加如下ActionScript:
gotoAndPlay(2);
该行语句令影片回到第2帧重新确定鱼身各节的位置。
(4)将荷花影片剪辑picMC拖放到图层2,并在属性面板中将其实例命名为picMC。选中该影片剪辑实例,在其动作面板中添加如下ActionScript:
duplicateMovieClip("picMC", "pic", 30);
该行语句复制荷花,并将其深度级别设为30。因为在鱼身各节中,鱼头的深度级别最高,为20,这里只要是一个大于20的数即可将荷花置于鱼的上面。
(5)按Ctrl+Enter测试影片,最终效果如图7-4所示。

7.3 单击影片剪辑
你也许会认为只有按钮才能被鼠标单击,其实并非如此,采用一些技巧,影片剪辑也能接受鼠标的单击动作,并且可以有几种方法实现这种功能。
7.3.1 将按钮置于影片剪辑中
影片剪辑本身并不能响应鼠标单击动作,所以不能像按钮一样使用on(release)或是on(press)等事件处理函数。要使影片剪辑响应鼠标单击动作,可以在影片剪辑中放入按钮。如前一章中的台球实例,在球杆影片剪辑中即加入了一个覆盖整个球杆的隐形按钮,当单击球杆(实际上是单击按钮)时,即令影片剪辑开始播放,执行击球的动作。
7.3.2 hitTest方法
在影片剪辑中加入按钮并不是让影片剪辑响应鼠标动作的唯一方法。事实上,你可以使用onClipEvent (mouseDown)或是onClipEvent (mouseUp)或是onClipEvent (mouseMove)等事件处理函数响应鼠标的动作,如在上一章的scale实例中,我们使用了onClipEvent (mouseMove)事件处理函数。
虽然影片剪辑中有这们的事件处理函数,但它与按钮的事件处理函数是有明显区别的。如影片剪辑的onClipEvent (mouseUp)事件,无论鼠标在什么位置单击,只要是包含该函数的影片剪辑都要执行相应的动作;而按钮的on (release)事件只有当鼠标在按钮上单击才会发生。例如本例文件,其中,为每个影片剪辑添加了如下的ActionScript:
onClipEvent (mouseUp) {
gotoAndStop(2);
}
当在窗口中的任意位置单击鼠标时,所有影片剪辑实例都转到第2帧。
这是因为所有影片剪辑都响应了mouseUp事件,而不区别鼠标单击的具体位置。
7.3.3 判断哪个影片剪辑被单击
正因为如此,要让影片剪辑像按钮一样准确地响应鼠标动作,就需要判断哪个影片剪辑被单击。
hitTest函数专门用来检测两个影片剪辑之间或影片剪辑和某一点之间是否相交。如将上例影片剪辑中的ActionScript改成如下所示:
onClipEvent (mouseUp) {
if (this.hitTest(_root._xmouse, _root._ymouse)) {
gotoAndStop(2);
}
}
以上语句在mouseUp事件发生时,判断鼠标位置所在点与当前影片剪辑之间是否相交,相交时执行命令gotoAndStop(2)。此时在窗口中单击鼠标,只有鼠标位置处的影片剪辑会转到第2帧
从例子中可以看出,Flash将影片剪辑所在的最小矩形范围作为影片剪辑的范围,所以在圆形的外切正方形区域单击鼠标同样会使hitTest函数为true。为了使hitTest函数只在圆形范围内为true,可以在hitTest函数中加入一个参数true,如下所示:
onClipEvent (mouseUp) {
if (this.hitTest(_root._xmouse, _root._ymouse, true)) {
gotoAndStop(2);
}
}
现在测试影片,只有在圆形内部单击鼠标,影片剪辑才会响应鼠标动作。
现在已经有两种方法可以使影片剪辑响应鼠标动作,一是在影片剪辑中加入按钮,另一种就是使用hitTest函数,两种方法各有所长,具体使用哪一种要视情况而定。使用hitTest函数会使影片剪辑和库都更精简,而按钮的up、down和over这3种状态对创建交互式的动画也是非常方便和有效的。
7.4 拖动影片剪辑
可以使用startDrag拖动一个影片剪辑,使用stopDrag停止对影片剪辑的拖动动作。
如本例文件,左下角有一只扇动翅膀的蝴蝶。
在蝴蝶上按下鼠标并拖动,蝴蝶会跟随鼠标飞舞;释放鼠标,蝴蝶在当前位置停下。如图7-8所示。按下鼠标拖动蝴蝶用到的ActionScript就是startDrag,释放鼠标停止拖动用到的ActionScript就是stopDrag。
多试几次,你会发现,将蝴蝶拖放到画面中的两朵花上,蝴蝶将不再扇动翅膀,而是静静地品尝花香。这是因为在花朵中央放置了一个透明的影片剪辑,使用hitTest函数判断该影片剪辑与蝴蝶影片剪辑是否相交,如果相交,则让蝴蝶停止在第1帧。
打开文件drag.fla,库中共有两个影片剪辑:蝴蝶和flower。放置两个flower的实例到两朵花的中心,在属性面板中将它们的分别命名为flower1和flower2,并将透明度设置为0%,让它们不可见。
选中蝴蝶影片剪辑实例,打开其动作面板,在其中添加如下ActionScript:
onClipEvent (mouseDown) {
if (this.hitTest(_root._xmouse, _root._ymouse, true)) {
this.startDrag(true);
play();
}
}
onClipEvent (mouseUp) {
if (this.hitTest(_root._xmouse, _root._ymouse, true)) {
this.stopDrag();
}
if (this.hitTest(_root.flower1) or this.hitTest(_root.flower2)) {
gotoAndStop(1);
}
}
在mouseDown事件中,判断是否与鼠标光标相交,如果是,开始拖动。
在mouseUp事件中,判断是否与鼠标光标相交,如果是,停止拖动;并且判断是否与flower1或flower2相交,如果是,停止在第1帧。
该例用到了hitTest函数的两个功能,即判断影片剪辑和鼠标所在点是否相交以及判断两个影片剪辑是否相交。该例还用到了一对很常用的命令:startDrag和stopDrag,使用它们可以方便地实现鼠标拖动操作。
仔细观察将会发现,蝴蝶停在花朵上的位置并不是很居中,这是因为只要两个影片剪辑的边缘相交,hitTest的值就会为true,为了使位置更精确一点,一种方法就是将flower影片剪辑做得更小一点,另一种方法就是修改上面的ActionScript,将判断两影片剪辑相交的一段代码改成如下所示:
if (_root.flower1.hitTest(this._x, this._y, true) or _root.flower2.hitTest(this._x, this._y, true)) {
gotoAndStop(1);
}
实际上,这种方法是将判断两个影片剪辑相交改成判断flower影片剪辑和蝴蝶影片剪辑的中心点相交,范围当然精确得多。

 

第8章 响应键盘

有4种方法可以检测键盘上的按键动作。第1种方法是使用按钮,第2种方法是使用Key对象,第3种方法是使用键盘侦听,第4种方法是使用影片剪辑的keyUp和keyDown事件处理函数。

8.1 通过按钮检测按键动作
在按钮的on事件处理函数中不但可以对鼠标事件作出响应,而且可以对键盘事件作出响应。如在按钮的动作面板中加入如下所示的代码,在敲击键盘上的A键时输出窗口中将提示:A is pressed。
on (keyPress "a") {
trace("A is pressed");
}
检测键盘上的字母键时,字母都应为小写。如果要检测键盘中的特殊键,如方向键,Flash中有一些专门的代码来表示它们,如表8-1所示。
表8-1 键盘中的特殊键
<Left> <Right> <Up> <Down> <Space>
<Home> <End> <Insert> <PageUp> <PageDown>
<Enter> <Delete> <Backspace> <Tab> <Escape>
如要检测键盘上的<End>键,可以使用下面的ActionScript:
on (keyPress "<End>") {
trace("End is pressed");
}
您可以在一个按钮中加入若干个on函数,也可以在一个on函数中结合多种事件,这使您可以为按钮定义快捷键,如下所示:
on (release, keyPress "<Left>") {
_root.myMC.prevFrame();
}
上面的语句实现单击按钮或按键盘上的左方向键,控制影片剪辑myMC回退1帧。
8.2 影片剪辑的keyUp和keyDown事件
影片剪辑包含两个与键盘相关的事件keyUp和keyDown,使用它们也可以实现对按键事件的响应,如下所示:
onClipEvent (keyDown) {
trace(Key.getAscii());
}
函数Key.getAscii返回与按键相对应的ASCII码。ASCII码是一个整数,键盘上的每个字符对应一个ASCII码,如字母A对应的ASCII码为65,B对应的ASCII码为66,a对应的ASCII码为97, b对应的ASCII码为98,+对应的ASCII码为43等。只有字符才有ASCII码,键盘上的功能键没有ASCII码。
如果需要在输出窗口中输出与按键相对应的字符,可以使用String对象的fromCharCode函数将ASCII码转换成字符,如将上例的trace命令改成如下所示:
trace(String.fromCharCode(Key.getAscii()));
String对象见动作面板的“对象”/“核心”目录下面。
8.3 Key对象
利用按钮检测按键动作很有效,但是并不利于检测持续按下的键,所以不适合于制作某些通过键盘控制的游戏。
这时,您就需要用到Key对象。Key对象包含在动作面板的“对象”/“影片”目录下面,它由Flash内置的一系列方法、常量和函数构成。使用Key对象可以检测某个键是否被按下,如要检测左方向键是否被按下,可以使用如下ActionScript:
if (Key.isDown(Key.LEFT)) {
trace("The left arrow is down");
}
函数Key.isDown返回一个布尔值,当该数中的参数对应的键被按下时返回true,否则返回false。常量Key.LEFT代表键盘上的左方向键。当左方向键被按下时,该函数返回true。
Key对象中的常量代表了键盘上相应的键,如表8-2所示。
表8-2 Key对象中的常量
Key.BACKSPACE Key.ENTER Key.PGDN
Key.CAPSLOCK Key.ESCAPE Key.RIGHT
Key.CONTROL Key.HOME Key.SHIFT
Key.DELETEKEY Key.INSERT Key.SPACE
Key.DOWN Key.LEFT Key.TAB
Key.END Key.PGUP Key.UP
以上是键盘上的功能键,那么如何表示键盘上的字母键呢?Key对象提供了一个函数Key.getCode来实现这一功能,如下所示:
if (Key.isDown(Key.getCode("a"))) {
trace("A is pressed");
}
8.4 键盘侦听
假设在影片剪辑的onClipEvent(enterFrame)事件处理函数中检测按键动作,而影片剪辑所在的时间轴较长,或计算机运算速度较慢,有可能出现这种情况,即当在键盘上按下某个键时还未来得及处理onClipEvent(enterFrame)函数,那么按键动作将被忽略。
还有一个问题就是,在某些游戏(如射击)中,我们需要按一次键就执行一次动作(发射一发子弹),即使长时间按住某个键不放也只能算作一次按键,而Key对象并不能区别是长时间按住同一个键还是快速地多次按键。
在解决这个问题,就需要用到Flash MX中的第3种方法:键盘侦听。when it comes to listening for key presses您可以使用 “侦听器(listener)”来侦听键盘上的按键动作。
要使用侦听器首先需要创建它,您可以使用如下所示的命令来告诉计算机您需要侦听某个事件:
Key.addListener(_root);
Key.addListener命令将主时间轴或某个影片剪辑作为它的参数,当侦听的事件发生时可以用这个参数指定的对象来响应该事件。
上面的代码指定主时间轴来响应该事件。要让主时间轴对该事件作出响应,还需要设置一个相应的事件处理函数。
键盘侦听的事件处理函数有两个:onKeyUp和onKeyDown,如下所示:
_root.onKeyUp = function() {
trace(Key.getAscii());
};
您也可以使用影片剪辑作为侦听键盘的对象,只需要使用影片剪辑的路径代替_root作为Key.addListener命令的参数。
8.5 练习:键盘控制影片剪辑
文件如图8-1所示,可以通过键盘上的方向键控制影片剪辑运动。当敲击空格键时,瓢虫回到初始位置。
文件ladybug.fla,其中包含了一个影片剪辑ladybug。在主场景中选中瓢虫影片剪辑,打开其动作面板,其中添加了如下ActionScript:
onClipEvent (load) {
x0 = this._x;
y0 = this._y;
}
onClipEvent (enterFrame) {
if (Key.isDown(Key.SPACE)) {
this._x = x0;
this._y = y0;
this._rotation = 0;
}
if ((Key.isDown(Key.LEFT)) && (Key.isDown(Key.UP))) {
this._x -= 10/Math.SQRT2;
this._y -= 10/Math.SQRT2;
this._rotation = -45;
} else if ((Key.isDown(Key.LEFT)) && (Key.isDown(Key.DOWN))) {
this._x -= 10/Math.SQRT2;
this._y += 10/Math.SQRT2;
this._rotation = -135;
} else if ((Key.isDown(Key.RIGHT)) && (Key.isDown(Key.UP))) {
this._x += 10/Math.SQRT2;
this._y -= 10/Math.SQRT2;
this._rotation = 45;
} else if ((Key.isDown(Key.RIGHT)) && (Key.isDown(Key.DOWN))) {
this._x += 10/Math.SQRT2;
this._y += 10/Math.SQRT2;
this._rotation = 135;
} else if (Key.isDown(Key.LEFT)) {
this._x -= 10;
this._rotation = -90;
} else if (Key.isDown(Key.RIGHT)) {
this._x += 10;
this._rotation = 90;
} else if (Key.isDown(Key.UP)) {
this._y -= 10;
this._rotation = 0;
} else if (Key.isDown(Key.DOWN)) {
this._y += 10;
this._rotation = 180;
}
if (this._x>550) {
this._x = 0;
}
if (this._x<0) {
this._x = 550;
}
if (this._y>400) {
this._y = 0;
}
if (this._y<0) {
this._y = 400;
}
}
当敲击空格键(Key.isDown(Key.SPACE))时,影片剪辑回到初始位置;当敲击不同的方向键或方向键组合时,相应调整影片剪辑的_x、_y和_rotation属性,从而实现以键盘控制影片剪辑。

第9章 输入文本和字符串

Flash中的文本形式有3种,即静态文本、动态文本和输入文本。输入文本可以接受用户输入,这也是响应键盘事件的一种。输入文本是一种人机交互工具,输入文本作为变量可以被ActionScript识别。
有许多方法可以操纵String(字符串)对象,如使用运算符“+”连接字符串,使用substring和substr函数从目标字符串中截取子字符串,使用indexOf函数确定匹配字符串在目标字符串中的位置等。


9.1 输入文本
Flash中的文本形式有3种,即静态文本、动态文本和输入文本。输入文本可以接受用户输入,这也是响应键盘事件的一种。
3种形式的文本都是由文本工具 创建的,要创建输入文本,首先要使用文本工具绘制一个文本框,然后在属性面板中将该文本框的类型设置成输入文本
在输入文本的属性面板中,除可以设置一般的文本格式外,还可以单击 按钮将文本显示为HTML格式,单击 按钮为文本添加边框,在 后面的下拉列表框中设置文本的换行格式或将文本设置成密码显示。
输入文本最重要的是变量名,如图9-2所示中的“变量”文本框,其中的myInputText即是该输入文本的变量名。输入文本变量和其他变量类似,变量的值会呈现在输入文本框中,输入文本框中的值同时也作为输入文本变量的值,它们之间是等价的。
如在场景中绘制了一个变量名为myInputText的输入文本框,然后在主时间轴的帧动作面板中添加如下ActionScript:
Key.addListener(_root);
_root.onKeyDown = function() {
trace(_root.myInputText);
};
以上脚本创建一个键盘侦听器,当按下键时即将输入文本myInputText中的内容显示在输出窗口中。测试一下您可以看到,输出窗口不会漏掉输入的每个字符,并且每输入一个字符即输出一行。
9.2 字符串
字符串是一种特殊类型的数据,对字符串可以进行多种操作。
9.2.1 连接字符串
要连接两个字符串,可以使用“+”运算符。如下所示:
var myString = "Hello";
myString += " World.";
trace(myString);
输出窗口中将输出如下所示的字符串:
Hello World.
您可以在一行ActionScript中使用多个“+”运算符,如下所示:
myStr1 = "How";
myStr2 = "are";
myStr3 = "you";
myStr = myStr1+" "+myStr2+" "+myStr3+"?";
trace(myStr);
输出窗口中将输出如下所示的字符串:
How are you?
9.2.2 截取字符串
从字符串中可以截取它的子字符串。例如,下面的脚本从字符串中截取第5到第14个字符组成的子字符串:
myString = "ActionScript is so useful!";
childStr = myString.substring(4, 14);
trace(childStr);
截取字符串函数substring有两个参数,第一个参数表示要截取的字符串的开始位置,第2个参数表示要截取的字符串的结束位置。
输出窗口中输出如下所示的子字符串:
onScript i
我们要截取的子字符串是从第5个开始,为什么substring的参数中要从4开始呢?这是因为在ActionScript中,通常是从0开始计数的,即上面的字符串中第0位上是A,第1位上是c,以此类推。那么既然从0开始计数,第14个字符就应该是第13位,为什么第2个参数不是13而是14呢?这是因为substring的第2个参数是指要截取到的位置,即要截取的最后一个字符是它前面的一个字符,所以它应该比要截取的最后一个字符多一位。
还有一种方法可以截取字符串,这就是substr。substr与substring命令的区别在于substr的第2个参数代表要截取的子字符串的长度。如下所示的ActionScript实现与前例相同的效果:
myString = "ActionScript is so useful!";
childStr = myString.substr(4, 10);
trace(childStr);
在输出窗口中输出子字符串:
onScript I
还有一个特殊的截取字符串的命令charAt。charAt可以从字符串的指定位置截取一个字符,如要从前面的字符串中截取第6位上的字符S,可以使用如下所示的ActionScript:
myString = "ActionScript is so useful!";
childStr = myString.charAt(6);
trace(childStr);
输出窗口中将输出字符S。
9.2.3 字符串函数
String对象有很多内置函数,使您可以对字符串进行各种操作。
indexOf方法用于从目标字符串中查找另一字符串的索引,即与另一字符串相匹配的子字符串的起始位置。如下所示:
myString = "Macromedia Flash MX";
myStr = myString.indexOf("Flash", 0);
trace(myStr);
以上脚本从目标字符串“Macromedia Flash MX”中查找字符串“Flash”的位置,运行该脚本,输出窗口中输出11。
如果目标字符串中没有找到相匹配的字符串,将返回-1。
indexOf的第2个参数表示从目标字符串中开始查找的起始位置,前例中的0表示从目标字符串的第1个字符开始查找。该参数可以省略,将默认从第1个字符开始查找。
与indexOf函数相对的是lastindexOf,用它查找在参数所指定的开始位置之前的最后一个子字符串的索引,即逆序查找。如下所示:
myString = "Macromedia Flash MX";
myStr = myString.lastindexOf("a", 12);
trace(myStr);
运行该脚本,输出窗口中输出9。
如果将参数12改成13或更大的数,或将该参数省略,将返回结果13。
String对象的toLowerCase函数实现将大写字母转换为小写形式,toUpperCase函数实现将小写字母转换为大写形式。如下所示:
myString = "Macromedia Flash MX";
myStr1 = myString.toLowerCase();
myStr2 = myString.toUpperCase();
trace("Original String : "+myString);
trace("LowerCase String : "+myStr1);
trace("UpperCase String : "+myStr2);
运行该脚本,输出窗口中显示:
Original String : Macromedia Flash MX
LowerCase String : macromedia flash mx
UpperCase String : MACROMEDIA FLASH MX
String对象只有一个属性,即length,它表示字符串的长度,即字符串中包含字符串的个数,如下所示:
myString = "Macromedia Flash MX";
trace(myString.length);
运行该脚本,输出窗口中显示19,即该字符串中共19个字符。
在使用String对象的函数和属性时要注意,字母的大写形式和小写形式是有区别的,并且每个空格也作为一个字符。
9.3 练习:表单
表单(form)在网页中使用得非常频繁,用户可以通过表单与服务器进行交互,从而实现注册或登录等操作。
借助于输入文本、按钮以及ActionScript等,也可以用Flash来制作网页中的表单。
第1个输入文本框采用单行格式,第2个输入文本框采用密码格式,第3个输入文本框采用多行格式,并设置了30像素的缩进。3个输入文本变量名分别为name、paword和words,使用ActionScript分别控制3个文本框中的最大字符数。当单击按钮Clear时,清除3个文本框中的内容,当单击按钮Submit时,提交所填的内容。因为这里还没学到Flash与服务器的交互,所以将用户所填内容通过输出窗口显示出来。
打开文件form.fla,分别查看一下3个输入文本框的属性面板中的设置。
在主场景中新建一层Actions,打开其动作面板,其中添加了如下ActionScript:
Key.addListener(_root);
_root.onKeyUp = function() {
if (_root.name.length>8) {
_root.name = _root.name.substr(0, 8);
}
if (_root.paword.length>16) {
_root.paword = _root.paword.substr(0, 16);
}
if (_root.words.length>150) {
_root.words = _root.words.substr(0, 150);
}
};
以上脚本控制3个文本框中的最大字符数,当在文本框中输入的字符数超过了限制,则使用substr函数从输入的字符串中截取指定长度的字符串。
选中按钮Clear,打开其动作面板,其中添加了如下ActionScript:
on (release) {
_root.name = "";
_root.paword = "";
_root.words = "";
}
选中按钮Submit,打开其动作面板,其中添加了如下ActionScript:
on (release) {
trace("Welcome "+_root.name+" !");
trace("Your password is "+_root.paword+" .");

第10章 动态文本

在制作游戏的时候,有时需要一个文本框来记录用户的游戏得分,这个分数是根据游戏情况动态改变的。这时候,我们就需要用到动态文本。
动态文本与输入文本的区别在于它不能直接接受用户输入。
但是,动态文本可以用来显示不同样式和字体的文本。

10.1 动态文本
和输入文本一样,使用文本工具可以创建动态文本框,只需在属性面板中选择“动态文本”即可
要让动态文本框动态地显示文本,就需要在属性面板中为其设置变量名。将动态文本的变量名设为myDynamicText。在Flash影片播放时,只需改变动态文本变量的值,就可以改变动态文本框中显示的文本。
动态文本有3种基本格式:单行、多行和多行不换行,它没有输入文本的密码格式。
属性面板中间有3个按钮,其中:
= :可选,它决定了是否可以对动态文本框中的文本执行选择、复制、剪切等操作,按下表示可选。如果是输入文本,它是默认按下并且不可改变的,因为输入文本一定是可选的。
= :将文本呈现为HTML,它决定了动态文本框中的文本是否可以使用HTML格式,即使用HTML语言为文本设置格式。
= :在文本周围显示边框,它决定了是否在动态文本框周围显示边框。
怎样才能让动态文本框显示需要的文本呢?如下所示的脚本即在变量名为myDynamicText的动态文本框中显示“Welcome to ActionScript!”:
myDynamicText = "Welcome to ActionScript!";
上面的脚本是加在动态文本所在的时间轴上的。
动态文本的使用虽然很简单,但是用它可以做许多事情。
10.2 HTML格式
HTML即超文本置标语言,它是网页格式的一种显示规范。在浏览网页时,浏览器通过解读HTML标记将网页中的各种元素显示成需要的样式。在Flash中可以使用HTML来设置动态文本的格式。要使用HTML,首先需要按下属性面板中的 按钮。在Flash中使用HTML标记为动态文本设置格式的ActionScript如下所示:
myDynamicText = "<B>B:粗体</B>.
";
myDynamicText += "<I>I:斜体</I>.
";
myDynamicText += "<U>U:下划线</U>.
";
myDynamicText += "<FONT COLOR='#F000F0'>FONT COLOR:颜色</FONT>.
";
myDynamicText += "<FONT FACE='Arial Black'>FONT FACE:字体</FONT>.
";
myDynamicText += "<FONT SIZE='28'>FONT SIZE:字号</FONT>.
";
myDynamicText += "<A HREF=' http://www.sina.com.cn& #39;>A HREF:超链接</A>.
";

Flash中使用的并不是完整的HTML,而只是HTML中的一些标记,使用这些标记可以轻松地为动态文本设置各种格式。
Flash MX中可用的所有HTML标记如下所示:
= <B></B>:粗体
= <I></I>:斜体
= <U></U>:下划线
= <FONT FACE='face'></FONT>:设置字体
= <FONT SIZE='size'></FONT>:设置字号
= <FONT COLOR='#XXXXXX></FONT>:设置颜色
= <A HREF='address'></A>:网页超链接
= <P></P>:定义段落
=
:换行
10.3 从文本文件中获取变量
通过ActionScript可以调用Flash影片外部文本文件中的变量。从外部文件中获取变量的方法非常有用,它可以在不改变Flash文件的基础上对Flash影片的内容作出修改。例如要用Flash制作一个天气预报动画,如果每天都对Flash文件进行修改就太麻烦了。而使用外部变量就只需要对文本文件作出修改。
要从外部文件中获取变量需要用到的命令是loadVariables,如下所示:
loadVariables("weather.txt", _root);
其中,第1个参数是Flash影片要获取变量的文件位置,第2个参数是文本变量要加载到的位置,可以是_root,也可以是某个影片剪辑或深度级别。Flash将来自外部文件中的变量值加载到与指定位置中具有相同变量名的文本字段中。
使用loadVariables命令要注意的是,指定的文本应以Flash影片中的文本变量名开始,否则不能被加载。本例weather.txt中的内容如下所示:
myDynamicText=Today is Friday,it's rainy!
打开文件loadVariables.fla,在主时间轴中有一个动态文本框,其变量名与weather.txt中的文本字段相同,当运行前面的脚本时,该文本框中显示:
Today is Friday,it's rainy!
如果在文本文件中为变量指定多行字符串,Flash将自动识别换行符,从而实现自动换行。
您可以修改文本文件中的内容,Flash中动态文本显示的内容也将作出相应的改变。
10.4 练习:滚动新闻
(1)新建一个Flash文档并保存。
(2)在场景中绘制一个动态文本框,在属性面板中将其变量名设为text。
(3)选中文本框,按F8键将其转换为影片剪辑元件,在属性面板中将该影片剪辑实例命名为news。
(4)选中影片剪辑实例news,打开其动作面板,在其中添加如下ActionScript:
onClipEvent (load) {
loadVariables("news.txt", news);
v = 0;
}
onClipEvent (enterFrame) {
v++;
if (v == 1) {
text = text.substr(1, text.length-1)+text.substr(0, 1);
v = 0;
}
}
在onClipEvent(load)事件中使用loadVariables命令将外部文件news.txt中的文本调入到Flash影片中。
变量v用来控制新闻滚动的速度。
在onClipEvent(enterFrame)事件中使用String对象的substr方法将text中的字符串分拆重组,以实现字符串滚动的效果。
(5)在与该Flash文档保存位置相同的位置创建一个文本文档news.txt,在其中添加如下所示的字符:
text=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
其中的text变量与Flash中的动态文本变量名相同,其后的字符串可以根据需要添加。测试影片,效果如图10-3所示。

第11章 Math对象

作为一门编程语言,进行数学计算是必不可少的。在数学计算中经常会使用到数学函数,如取绝对值、开方、取整、求三角函数值等,还有一种重要的函数是随机函数。ActionScript将所有这些与数学有关的方法、常数、三角函数以及随机数都集中到一个对象里面——Math对象。
Math对象是ActionScript的一块敲门砖,只有掌握了它,才能真正对ActionScript动画编程做到运用自如。

11.1 Math对象的方法
11.1.1 Math.abs
Math对象中集合了许多常用数学函数。Math.abs就是用来计算一个数的绝对值,即一个数去掉正负符号后的值。其用法如下:
x=Math.abs(-9);
或:
x=Math.abs(num1-num2);
11.1.2 Math.round
Math.round方法将一个浮点数四舍五入为最接近的整数,如:
trace(Math.round(9.4));
trace(Math.round(9.5));
trace(Math.round(-9.4));
trace(Math.round(-9.5));
trace(Math.round(-9.6));
输出窗口中将显示:
9、10、-9、-9、-10
11.1.3 Math.ceil、Math.floor
Math.ceil方法取比一个浮点数大且最接近的整数,Math.floor方法取比一个浮点数小且最接近的整数。如:
trace(Math.ceil(9.1));
trace(Math.floor(9.1));
trace(Math.ceil(-9.1));
trace(Math.floor(-9.1));
输出窗口中将显示:
10、9、-9、-10
11.1.4 Math.min、Math.max
Math.min方法取两个数中较小的一个数,Math.max方法取两个数中较大的一个数,如:
trace(Math.min(9, 8));
trace(Math.max(9, 8));
输出窗口中显示:
8、9
11.1.5 Math.pow
Math.pow方法用来计算一个数的乘方,它包含两个参数,第1个参数是底数(要乘方的数),第2个参数是幂(乘方数)。如计算5的3次方:
trace(Math.pow(5, 3));
输出窗口中显示:
125
Math.pow方法也可以计算一个数的开方,如计算125的开3次方:
trace(Math.pow(125, 1/3));
输出窗口中显示
5
11.1.6 Math.sqrt
除了用Math.pow计算一个数的开方,还可以使用Math.sqrt计算一个数的平方根,如计算64的平方根:
trace(Math.sqrt(64));
输出窗口中显示
8
它等同于:
trace(Math.pow(64, 1/2));
11.2 Math对象的常数
Math对象的常数有以下几个:
= Math.PI:圆周率(大约为3.141593)。
= Math.SQRT1_2:1/2的平方根的倒数(大约为0.707107)。
= Math.SQRT2:2的平方根(大约为1.414214)。
= Math.E:欧拉(Euler)常数,自然对数的底(大约为2.718282)。
= Math.LN2:2的自然对数(大约为0.693147)。
= Math.LN10:10的自然对数(大约为2.302585)。
= Math.LOG2E:e的以2为底的对数(大约为1.442695)。
= Math.LOG10E:e的以10为底的对数(大约为0.434294)。
其中Math.PI用得较多,如下面的脚本将弧度值arcdegree转换为角度值angledegree:
angledegree = arcdegree*(180/Math.PI);
下面的ActionScript将弧度1转换为角度:
arcdegree = 1;
angledegree = arcdegree*(180/Math.PI);
trace(angledegree);
输出窗口中显示:
57.2957795130823
11.3 三角函数
Math对象中的三角函数有:
= Math.sin:正弦
= Math.cos:余弦
= Math.tan:正切
= Math.asin:反正弦
= Math.acos:反余弦
= Math.atan:反正切
= Math.atan2:从x坐标轴到点的角度
三角函数在ActionScript中有着举足轻重的地位,它们在制作一些特效动画时将发挥重要的作用。
在程序语言中通常以x和y标记位置,但是在一个圆周上使用x和y来标记位置并不是很容易。三角函数在处理与圆周相关的位置参数时很有效。如用某个圆的圆心位置为(x0,y0),半径为r,可以用y0+r*Math.sin(0)表示该圆水平直径右端点的纵坐标,用x0+r*Math.cos(0)表示该圆水平直径右端点的横坐标。
如下所示的ActionScript使影片剪辑绕圆周运动:
onClipEvent (load) {
i = 0;
r = 150;
x0 = 275;
y0 = 200;
}
onClipEvent (enterFrame) {
i += 10;
this._x = x0+r*Math.cos(i/(180/Math.PI));
this._y = y0+r*Math.sin(i/(180/Math.PI));
}
此时的影片剪辑是沿顺时针方向转动的,如要让它沿相反方向转动,只需将i += 10改写成i -= 10即可。
ActionScript中的三角函数都是按照弧度计算的。一个完整圆周的弧度数为2*Math.PI,大约是6.283185,而一个圆周的角度数是360。如要在三角函数中使用角度数,需要将其除以180/Math.PI以转换为弧度数。
在上面的脚本中,i的值是递增的,而并没有限定在0~360之间。这是因为正弦函数和余弦函数是定义在负无穷~正无穷上的周期函数,它们的值是以360°为周期循环的。
11.4 字符串和数字的转换
在ActionScript中,字符串和数字之间可以相互转换。在很多时候,将字符串转换为数字或将数字转换为字符串都是很有必要的。例如,在Flash中有一个变量名为n的输入文本框和一个按钮,按钮中的ActionScript如下:
on (release) {
trace(n+7);
}
当在输入文本框中输入11,再单击按钮时,输出窗口将显示字符串“11”与字符串“7”相加的结果117,而不是数字11与数字7相加的结果8。这是因为从输入文本框中获得的是字符串,当表达式中有字符串和数字时,ActionScript优先考虑字符串,将数字转换为字符串后再进行字符串运算。
为了将字符串转换成数字,可以使用ActionScript提供的函数Number,如将上例所示的脚本改写成如下所示:
on (release) {
trace(Number(n)+7);
}
当在输入文本框中输入11,再单击按钮时,输出窗口将显示结果18。
如果Number函数中的参数不能转换成数字,则返回结果NaN。
以“0x”开头的字符串将被解释为十六进制数。
对于布尔值,true将转换为1,false将转换为0。例如将上例所示的脚本改写成如下所示:
on (release) {
n = n>10;
trace(Number(n));
}
当输入的值小于等于10时,输出窗口中显示0;当输入的值大于10时,输出窗口中显示1。
除了Number函数以外,函数parseInt可以将字符串转换成整数,函数parseFloat可以将字符串转换为浮点数。如将上例所示的脚本改写成如下所示:
on (release) {
trace(parseInt(n)+7);
trace(parseFloat(n)+7);
}
当在输入文本框中输入11.99,再单击按钮时,输出窗口中将显示18和18.99。
parseInt和parseFloat在处理字符串时比Number函数更专业一点,它们可以从字符串中取出能转换成数字的最长字符串进行转换,而忽略后面不能转换成数字的字符串。如将上例的脚本改写成如下所示:
on (release) {
trace(Number(n)+7);
trace(parseInt(n)+7);
trace(parseFloat(n)+7);
}
当在输入文本框中输入11t7.9并单击按钮时,输出窗口中将显示
NaN、18、18
parseInt函数可以有两个参数,第2个参数在2~36之间,表示要转换的数字的基数,即进制数。如将二进制数1101转换为十进制整数:
trace(parseInt(1101, 2));
输出窗口中显示13。
要将数字转换成字符串可以使用Number对象(动作面板的“对象”/“核心”目录)的toString方法。要使用toString方法需要先创建一个Number对象,其用法如下:
myNumber = new Number(15);
trace(myNumber.toString(2));
trace(myNumber.toString(16));
toString中的参数与parseInt函数的第2个参数一样,都表示进制数。本例中的2和16分别表示将myNumber转换为二进制数和16进制数。运行脚本,输出窗口中显示
1111
f
如果省略参数,默认为十进制。
11.5 随机数
随机数在Flash中的应用非常广泛。
在Flash 5以前的版本中,使用random函数获取一个近似的随机数,如random(10)随机返回0~9这10个整数中的一个。但在Flash MX中推荐使用Math对象的random方法,即Math.random(),该方法返回一个大于或等于0并且小于1的随机浮点数。
Math.random方法比random函数得到的结果更精确,但它并不能直接产生一个整数。我们可以使用别的办法将Math.random方法产生的随机数转换为我们需要的整数,如要得到一个1~10之间的随机整数,可以使用如下所示的ActionScript:
trace(Math.floor(Math.random()*10+1));
11.6 练习:下雪
打开文件snow.fla,这是一个利用attachMovie和Math.random方法制作的下雪效果,其中每一片雪花的大小、方向各不相同
该动画中形状各异的雪花与Math.random函数密不可分,下面来看它的制作方法。
(1)在库面板中为snow影片剪辑创建链接,其链接标识符为snow
(2)将snow元件拖到场景中,选中该影片剪辑实例,在其中添加如下ActionScript:
onClipEvent (load) {
this._visible = false;
v0 = 3; //速度
num = 50; //数量
vx = new Array(); //记录水平速度的数组
vy = new Array();成 //记录垂直速度的数组
for (var i = 1; i<=num; i++) {
_root.attachMovie("snow", "snow"+i, i); //附加num个影片剪辑实例
scale = 100*Math.random()+50; //随机设定实例大小
with (_root["snow"+i]) { //with语句
_xscale = scale;
_yscale = scale;
_x = 500*Math.random(); //随机出现在影片水平宽度范围
_y = 400*Math.random(); //随机出现在影片垂直高度范围
_rotation = 360*Math.random(); //随机旋转一个角度
vx[i] = v0*Math.random()+v0; //随机取得水平方向上的速度
vy[i] = v0*Math.random()+v0; //随机取得垂直方向上的速度
}
}
}
onClipEvent (enterFrame) {
for (var i = 1; i<=num; i++) {
with (_root["snow"+i]) {
_x += vx[i]; //在水平方向上运动
_y += vy[i]; //在垂直方向上运动
if (_x<0) { //超出左边界,从右边界进入
_x = 500;
}
if (_x>500) { //超出右边界,从左边界进入
_x = 0;
}
if (_y>400) { //超出下边界,从上边界进入
_y = 0;
}
}
}
}
以上脚本除了用到数组、attachMovie、Math.random等知识外,还用到了with动作。with动作用来为一组动作脚本指定一个对象,如本例用with动作指定对象_root["snow"+i],并在其后的大括号中对该对象的多种属性进行修改,从而避免了为每一个属性重复指定相同的对象,使脚本更紧凑和更简化。

 

第12章 Color对象

运用好的色彩可以使Flash作品具有更大的感染力,许多好的作品在色彩搭配和控制上都做得很成功。
在ActionScript中,Color对象专门用来管理颜色。使用Color对象可以实现许多色彩特效。

12.1 Color对象
使用ActionScript中的Color对象(动作面板的“对象”/“影片”目录)可以改变影片剪辑的颜色,Color对象的setRGB方法用来设置影片剪辑实例对象的RGB值。但是并不能对影片剪辑直接使用setRGB命令,在使用Color对象的方法之前首先需要创建Color对象的实例,如下所示:
myColor = new Color(myMC);
其中的参数myMC是要改变颜色的目标影片剪辑,创建Color对象的实例之后即可调用Color对象的方法,如下所示:
myColor.setRGB(0xFF0000);
setRGB的参数是以十六进制表示的,0x表示十六进制,后面的6位数字每两位为一组,分别表示红、绿、蓝3种颜色成份。如0xFF0000表示纯红,0x00FF00表示纯绿,0x0000FF表示纯蓝,0xFFFF00表示纯黄。
当然,也可以用十进制的数字代替十六进制,如下所示:
myColor1 = new Color(myMC1);
myColor2 = new Color(myMC2);
myColor1.setRGB(0xFFFF00);
myColor2.setRGB(255*256*256+255*256);
trace(myColor1.getRGB().toString(16));
trace(myColor2.getRGB().toString(16));
其中,Color对象的getRGB方法用来获取由setRGB方法指定的颜色值。
运行脚本,输出窗口中输出:
ffff00
ffff00
在这里,使用十六进制比十进制要方便得多。
12.2 练习:改变影片剪辑的颜色
下面是一个应用Color对象的例子,通过选择颜色面板中的颜色方格,为汽车添加相应的颜色,如图12-1所示。
其中,颜色面板的每个方格中都有一个透明按钮,在每个按钮中添加ActionScript,从而逼真地模仿了Flash的颜色面板。
该例的制作过程如下:
(1)建立影片剪辑panel,第1层放置颜色面板的原始位图;第2层放置动态文本框,用来显示颜色的RGB值,如图12-1所示的#FF0033,动态文本变量名为colortext;第3层放置影片剪辑colorarea,当鼠标滑过颜色面板时,显示鼠标经过方格的颜色,它的实例名也为colorarea;第4层为每个颜色方格放置一个按钮cb,并在属性面板中将其alpha值设置为0。
(2)将影片剪辑panel拖放到场景中。
(3)新建1层colorcar,将经过处理的图片car.jpg导入进来,选择“修改”/“转换位图为矢量图”命令将其转换为矢量图,并将颜色填充为白色, 将汽车位图转换为矢量图
(4)按F8键将白色的汽车矢量图转换为影片剪辑元件colorcar,并在场景中将其实例命名为colorcar。
(5)在主场景中新建1层car,导入事先处理好的图片car.png,这里使用png格式的图片是因为它保留了alpha通道,即具有透明度。将car.png与第2层中的colorcar影片剪辑对齐将car.png和colorcar对齐
(6)重新进入颜色面板panel影片剪辑,为其中的按钮添加ActionScript。如为左上角第1个黑色方格的按钮添加的ActionScript如下所示:
on (rollOver) { //鼠标经过时
colortext = "#000000"; //在动态文本区中显示方格的RGB值
mycolor = new Color(colorarea);
mycolor.setRGB(0x000000); //将左上角颜色框设置成方格的颜色
}
on (rollOut) { //鼠标移出时
colortext = ""; //动态文本区中不显示
mycolor.setRGB(0xFFFFFF); //将左上角颜色框设置成白色
}
on (release) { //单击鼠标时
carbody = new Color(_root.colorcar);
carbody.setRGB(0x000000); //将colorcar设置成单击处方格的颜色
}
为第1列第7个红色方格的按钮添加的ActionScript如下所示:
on (rollOver) {
colortext = "#FF0000";
mycolor = new Color(colorarea);
mycolor.setRGB(0xFF0000);
}
on (rollOut) {
colortext = "";
mycolor.setRGB(0xFFFFFF);
}
on (release) {
carbody = new Color(_root.colorcar);
carbody.setRGB(0xFF0000);
}
其他按钮中的脚本与上类似,相应的RGB值可以在Flash的颜色面板中查找。
(7)按Ctrl+Enter测试影片,效果如图12-1所示。

 

第13章 Date对象

Date 对象使您可以获取相对于通用时间(格林尼治平均时,现在叫做通用时间或 UTC)或相对于运行 Flash Player 的操作系统的日期和时间值。Date 对象的方法不是静态的,但仅应用于调用方法时指定的 Date 对象的单个实例。Date.UTC 方法是个例外,它是一个静态方法。
Date 对象以不同的方式处理夏时制,具体取决于操作系统和 Flash Player 的版本。
若要调用 Date 对象的方法,必须首先使用 Date 对象的构造函数创建一个 Date 对象的实例。

13.1 Date对象
Date对象(动作面板的“对象”/“核心”目录)也是ActionScript重要的内置对象之一。Date对象提供了很多处理通用时间(格林威治时间)或系统时间的方法。
Date对象由七部分构成,它们是:
= year:0~99表示1900~1999年,如果要表示在此以外的年,必须使用完整的4位数字。
= month:0~11表示1月~12月。
= date:1~31表示日期。
= hour:0~23表示小时数。
= minute:0~59表示分钟数。
= second:0~59表示秒数。
= millisecond:0~999表示毫秒数。
Date对象主要有两种创建方法,一种是通过指定时间创建一个Date对象的实例,这时至少要用到year和month两个参数,如下所示:
myDate = new Date(2003, 7, 8, 13, 16, 500);
另一种方法是通过获取系统时间创建一个Date对象的实例,这时不指定任何参数,如下所示:
myDate = new Date();
创建Date对象后即可使用Date对象的方法。如下所示:
myDate = new Date();
year = myDate.getYear();
fullyear = myDate.getFullYear();
month = myDate.getMonth();
dates = myDate.getDate();
hour = myDate.getHours();
minute = myDate.getMinutes();
second = myDate.getSeconds();
millisecond = myDate.getMilliseconds();
day = myDate.getDay();
time = myDate.getTime();
trace(year+","+fullyear+","+month+","+dates+","+hour+","+minute+","+second+","+millisecond+","+day+","+time);
getYear方法返回简写年份,如1999年返回99,2003年返回103。
getFullYear方法返回完整的4位数年份,如2003年返回2003。
getMonth方法返回月份,如7月返回6。
getDate方法返回日期,如7月16日返回16。
getHours方法返回小时数,如下午1点返回13。
getMinutes、getSeconds和getMilliseconds方法分别返回分钟、秒和毫秒数。
getDay方法返回星期数,星期日返回0,星期一返回1,以此类推。
getTime方法返回自1970年1月1日上午8时至Date对象所指时间的毫秒数。
运行脚本,输出窗口中显示:
103,2003,6,8,13,56,45,679,2,1057643805679
即:2003年7月8日13点56分45秒679毫秒,星期二,距离1970年1月1日上午8时共1057643805679毫秒。
13.2 练习:万年历
使用该例万年历可以翻查任何一年任何一月的日历,单击返回按钮可以查看当天所在的月份,且当天以白色显示。本例的制作过程如下:
(1)在图层back加入背景图片back.jpg。
(2)在图层yearmonth添加两个动态文本框,变量名为displaymonth和displayyear,分别用来显示月和年,字体为Vineta BT,颜色为黄色。
(3)在图层button添加按钮,分别用来控制月份上翻查、月份下翻查、年份上翻查、年份下翻查和返回当天。
(4)建立一个影片剪辑元件daynum,在其中添加一个变量名为num的动态文本框,用来显示日期,它的颜色为绿色。在库面板中为daynum元件添加链接,链接标识符也为daynum。
(5)在图层Actions的第1帧中添加如下ActionScript:
MyDate = new Date(); //创建Date对象以获取系统时间
MyCurYear = MyDate.getFullYear();
MyCurMonth = MyDate.getMonth();
MonthNames = new array(); //记录每个月名称的数组
DaysOfMonth = new array(); //记录每个月天数的数组
if (MyCurMonth == 1) { //如果是二月,判断是否为闰年
if ((MyNewYear%4 == 0) && (MyNewYear%100 != 0) || (MyNewYear%400 == 0)) {
DaysOfMonth[1] = 29;
} else {
DaysOfMonth[1] = 28;
}
}
MonthNames[0] = "January";
MonthNames[1] = "February";
MonthNames[2] = "March";
MonthNames[3] = "April";
MonthNames[4] = "May";
MonthNames[5] = "June";
MonthNames[6] = "July";
MonthNames[7] = "August";
MonthNames[8] = "September";
MonthNames[9] = "October";
MonthNames[10] = "November";
MonthNames[11] = "December";
DaysOfMonth[0] = 31;
DaysOfMonth[2] = 31;
DaysOfMonth[3] = 30;
DaysOfMonth[4] = 31;
DaysOfMonth[5] = 30;
DaysOfMonth[6] = 31;
DaysOfMonth[7] = 31;
DaysOfMonth[8] = 30;
DaysOfMonth[9] = 31;
DaysOfMonth[10] = 30;
DaysOfMonth[11] = 31;
(6)在Actions层的第3帧插入关键帧,在其动作面板中添加如下ActionScript:
stop();
MyNewDate = new Date(MyCurYear, MyCurMonth, 1); //根据参数创建Date对象
MyNewYear = MyNewDate.getFullYear();
MyNewMonth = MyNewDate.getMonth();
displaymonth = MonthNames[MyNewMonth]; //根据Date对象设置显示的月份
displayyear = MyNewYear; //根据Date对象设置显示的年份
if (MyNewMonth == 1) {
if ((MyNewYear%4 == 0) && (MyNewYear%100 != 0) || (MyNewYear%400 == 0)) {
DaysOfMonth[1] = 29;
} else {
DaysOfMonth[1] = 28;
}
}
MyDaysOfMonth = DaysOfMonth[MyNewDate.getMonth()];
MyDay = MyNewDate.getDay();
for (i=1; i<=Number(MyDaysOfMonth); i++) { //显示当月的所有天数
attachMovie("daynum", "daynum"+i, i); //附加显示日期的影片剪辑
_root["daynum"+i].num = i; //修改影片剪辑内的动态文本
if (i == 1) { //如果是每月的第1天
if (MyDay == 0) { //星期日
_root.daynum1._x = 50; //_x坐标为50,位于SUN下面
} else if (MyDay == 1) {
_root.daynum1._x = 100;
} else if (MyDay == 2) {
_root.daynum1._x = 150;
} else if (MyDay == 3) {
_root.daynum1._x = 200;
} else if (MyDay == 4) {
_root.daynum1._x = 250;
} else if (MyDay == 5) {
_root.daynum1._x = 300;
} else if (MyDay == 6) {
_root.daynum1._x = 350;
}
_root.daynum1._y = 130; //_y坐标为130
} else { //如果不是第1天
_root["daynum"+i]._x = _root["daynum"+(i-1)]._x+50; //_x坐标增加50
_root["daynum"+i]._y = _root["daynum"+(i-1)]._y; //_y坐标不变
if (_root["daynum"+i]._x>350) { //_x坐标超出星期六
_root["daynum"+i]._x = 50; //回到星期日的位置
_root["daynum"+i]._y += 40; //_y坐标下移40
}
if (_root["daynum"+i]._y>290) { //_y坐标超出下边界
_root["daynum"+i]._y = 130; //回到第一行显示
}
}
}
MyNewDate = new Date(); //获取系统时间
colorday = MyNewDate.getDate(); //获取要以白色显示的日期
if ((_root.displayyear == MyNewDate.getFullYear()) && (_root.displaymonth == MonthNames[MyNewDate.getMonth()])) { //如果显示的月份为当前月份
MyColor = new Color(_root["daynum"+colorday]); //将当前日期设置成白色
MyColor.setRGB(0xFFFFFF);
}
(7)为年份上翻查按钮的动作面板添加如下ActionScript:
on (release) {
for (j=1; j<=31; j++) {
removeMovieClip("daynum"+j); //单击时删除显示的日期
}
MyCurYear–; //年份变量减1
gotoAndPlay(2); //回到第2帧创建新的Date对象
}
(8)为年份下翻查按钮的动作面板添加如下ActionScript:
on (release) {
for (j=1; j<=31; j++) {
removeMovieClip("daynum"+j); //单击时删除显示的日期
}
MyCurYear++; //年份变量加1
gotoAndPlay(2); //回到第2帧创建新的Date对象
}
(9)为月份上翻查按钮的动作面板添加如下ActionScript:
on (release) {
for (j=1; j<=31; j++) {
removeMovieClip("daynum"+j); //单击时删除显示的日期
}
MyCurMonth–; //月份变量减1
if (MyCurMonth == -1) {
MyCurMonth = 11;
MyCurYear–;
}
gotoAndPlay(2); //回到第2帧创建新的Date对象
}
(10)为月份下翻查按钮的动作面板添加如下ActionScript:
on (release) {
for (j=1; j<=31; j++) {
removeMovieClip("daynum"+j); //单击时删除显示的日期
}
MyCurMonth++; //月份变量加1
if (MyCurMonth == 12) {
MyCurMonth = 0;
MyCurYear++;
}
gotoAndPlay(2); //回到第2帧创建新的Date对象
}
(11)为返回按钮的动作面板添加如下ActionScript:
on (release) {
for (j=1; j<=31; j++) {
removeMovieClip("daynum"+j); //单击时删除显示的日期
}
gotoAndPlay(1); //回到第1帧获取系统时间
}
(12)按Ctrl+Enter测试影片,效果如图13-1所示。

 

第14章 Sound对象

在时间轴中直接嵌入声音是制作Flash MV的一种通用手法,但是这种方法除了从头至尾地播放声音外,并不能对声音进行很好的控制。ActionScript内置的Sound对象(动作面板的“对象”/“影片”目录)为我们提供了管理和控制声音的一种好方法。


14.1 attachSound方法
Sound对象的attachSound方法与MovieClip对象的attachMovie方法类似,它在影片播放时将库中的声音元件附加到场景中。要使用该方法将声音附加到场景中,首先需要在库中为声音添加链接,为声音元件添加链接和为影片剪辑元件添加链接的方法类似,在要添加链接的声音元件中单击鼠标右键,在弹出的快捷菜单中选择“链接”命令,弹出“链接属性”对话框,
与Color对象和Date对象等其他内置对象一样,在使用Sound对象需要创建Sound对象的新实例,如下所示:
mySound = new Sound();
创建Sound对象的实例之后即可调用声音元件的链接,如下所示:
mySound.attachSound("music");
其中,attachSound方法的参数即是库中为声音元件添加的链接。仅仅执行以上操作还不够,必须使用下面的ActionScript让声音开始播放:
mySound.start();
如果操作执行无误,测试影片,一首动人的化蝶便开始播放了。
要停止用Sound对象播放的声音,可以使用如下所示的ActionScript:
mySound.stop();
14.2 练习:用按钮点歌
下面用以上的方法制作一个使用按钮点歌的影片,以加深对attachMovie方法的印象。
打开文件attachSound.fla,场景中添加了4个按钮和1个空影片剪辑,库中包含3个添加了链接的声音元件,它们的链接标识符分别为music1~music3,如图14-3所示

图14-3 attachSound.fla文件的编辑场景
在空影片剪辑的动作面板中添加如下所示的ActionScript:
onClipEvent (load) {
_root.turn = 1;
}
变量turn用来记录当前播放的曲目位置。
第2个按钮用来播放当前位置的曲目,在它的的动作面板中添加如下所示的ActionScript:
on (release) {
mySound.stop();
mySound = new Sound();
mySound.attachSound("music"+_root.turn);
mySound.start();
}
不管当前是否有曲目正在播放,单击该按钮都将重新加载当前曲目,并从头开始播放。
第3个按钮用来停止播放当前位置的曲目,在它的动作面板中添加如下所示的ActionScript:
on (release) {
mySound.stop();
}
单击该按钮,Sound对象停止播放。
第1个按钮用来使当前曲目回退一首并开始播放,在它的动作面板中添加如下所示的ActionScript:
on (release) {
mySound.stop();
_root.turn–;
if (_root.turn<1) {
_root.turn = 3;
}
mySound = new Sound();
mySound.attachSound("music"+_root.turn);
mySound.start();
}
单击该按钮,曲目位置回退一首,并判断是否超出第1首,如果是,则跳到第3首,从而实现循环。
第4个按钮的作用与第1个按钮相反,它使当前曲目前进一首并开始播放,在它的动作面板中添加如下所示的ActionScript:
on (release) {
mySound.stop();
_root.turn++;
if (_root.turn>3) {
_root.turn = 1;
}
mySound = new Sound();
mySound.attachSound("music"+_root.turn);
mySound.start();
}
单击该按钮,曲目位置前进一首,并判断是否超出第3首,如果是,则跳到第1首,从而实现循环。
14.3 loadSound方法
使用attachSound方法虽然可以动态地加载声音,但前提是需要将声音预先加入到库中,这样并不能避免文件过大的弊端。使用Sound对象的loadSound方法可以将Flash文件以外的MP3声音文件加载到影片中进行播放,这样可以有效地解决文件过大且播放的曲目有限的缺陷,使用loadSound方法可以播放计算机或网络中的任何MP3文件。
loadSound方法如下所示:
mySound.loadSound("url", isStreaming);
其中,url是指定要载入的MP3文件在计算机或网络中的路径,isStreaming是一个布尔值,用于指示加载的声音是作为事件声音还是作为声音流,为false时表示作为事件声音,为true时表示作为声音流。
事件声音在完全加载后才能播放。它们由动作脚本 Sound 对象进行管理,而且响应此对象的所有方法和属性。声音流在下载的同时播放。当接收的数据足以启动解压缩程序时,播放开始。
与attachMovie方法类似,使用loadSound方法的过程是:创建Sound对象、使用loadSound方法载入MP3文件、使用start命令播放声音以及使用Sound对象的其他方法控制声音或使用stop命令停止声音。
14.4 练习:从计算机中加载MP3
打开文件loadSound.fla,
其中有一个输入文本框,一个播放按钮和一个停止按钮。输入文本框的变量名为sound_url,在播放按钮的动作面板中添加了如下ActionScript:
on (release) {
mySound.stop();
mySound = new Sound();
mySound.loadSound(sound_url, false);
mySound.start();
}
单击该按钮,从输入文本框sound_url中获取MP3文件的路径,并将其作为事件声音(第2个参数为false)加载到影片中进行播放。
在停止按钮的动作面板中添加如下ActionScript:
on (release) {
mySound.stop();
}
单击该按钮,声音停止播放。
14.5 调节和控制声音
Sound对象不仅提供了动态加载声音、播放和停止声音的方法,而且也提供了调节声音和控制进度等方法,综合使用这些方法,完全可以用Flash做出一个具有较高品质的音乐播放器。
= start方法
如前所示,不使用参数时,start方法简单地从开始位置播放声音;start方法也可以接受参数,如下所示:
mySound.start(secondOffset, loop);
参数secondOffset指定声音开始播放的位置,如指定10,将从第10秒的位置开始播放声音。参数loop指定声音的循环次数。
= setVolume方法
setVolume方法用来设置音量,其使用方法如下所示:
mySound.setVolume(volume);
参数volume的值位于0~100之间,0表示无音量,100表示最大音量,声音播放时默认的音量为100。
= setPan方法
setPan方法用来设置声音的左右均衡,其使用方法如下所示:
mySound.setPan(pan);
参数pan的值位于-100~100之间,-100表示仅使用左声道,100表示仅使用右声道,0表示左右声道均衡。
= getBytesTotal方法
getBytesTotal方法以字节为单位返回声音对象的总大小。
= duration属性
Sound对象的duration属性返回整个声音对象持续的毫秒数。
= position属性
Sound对象的position属性返回声音已播放的毫秒数。
使用duration属性和position属性可以方便地控制声音的播放进度,这在制作播放器时是非常有用的。
= onSoundComplete事件处理函数
当声音播放完时自动调用onSoundComplete事件处理函数。
14.6 练习:MP3播放器
单击打开文件按钮可以打开一个输入文本框,在其中可以输入MP3文件的路径,单击关闭文件按钮可以关闭输入文本框。
左边的五个按钮分别用于控制MP3的播放、快进、快退、暂停、停止,右边的三个游标分别用于控制音量、声道和显示MP3的播放进度。
当播放MP3时,控制相关影片剪辑播放动画,当MP3停止时,所有动画同时停止。播放器上部还显示了日期和时间。在播放器上按下鼠标可以拖动播放器到任意位置。
下面来看MP3播放器的制作过程。
(1)在影片剪辑实例url的动作面板中添加如下ActionScript:
onClipEvent (load) {
_visible = false; //隐藏输入文本框
}
(2)在打开文件按钮的动作面板中添加如下ActionScript:
on (release) {
_root.url._visible = true; //显示输入文本框
}
(3)在关闭文件按钮的动作面板中添加如下ActionScript:
on (release) {
_root.url._visible = false; //隐藏输入文本框
}
(4)在播放按钮的动作面板中添加如下ActionScript:
on (release) {
_root.music.stop();
_root.music = new Sound();
_root.music.loadSound(_root.url.music_url, false);
//music_url是输入文本变量名,它所在的影片剪辑实例名为url
_root.music.start(); //开始播放
_root.music.onSoundComplete = function() { //播放结束时停止相关动画
_root.face.mcphone.gotoAndStop(1);
_root.face.tyre.gotoAndStop(1);
_root.scene.gotoAndStop(1);
};
if (_root.music.getBytesTotal()>0) { //有声音载入时开始相关动画
_root.face.mcphone.gotoAndPlay(2);
_root.face.tyre.gotoAndPlay(2);
_root.scene.gotoAndPlay(2);
}
}
(5)在停止按钮的动作面板中添加如下ActionScript:
on (release) { //停止声音和相关动画
_root.music.stop();
_root.face.mcphone.gotoAndStop(1);
_root.face.tyre.gotoAndStop(1);
_root.scene.gotoAndStop(1);
}
(6)在快进按钮中添加如下ActionScript:
on (release) {
if ((_root.music.position/_root.music.duration)<0.95) {
pos = _root.music.position/1000; //获取MP3的当前进度
_root.music.stop();
_root.music.start((pos+0.05*_root.music.duration/1000), 1);
//从当前进度快进5%开始播放
if (_root.music.getBytesTotal()>0) { //有声音载入时播放相关动画
_root.face.mcphone.gotoAndPlay(2);
_root.face.tyre.gotoAndPlay(2);
_root.scene.gotoAndPlay(2);
}
} else {
_root.music.stop();
_root.face.mcphone.gotoAndStop(1);
_root.face.tyre.gotoAndStop(1);
_root.scene.gotoAndStop(1);
}
}
(7)在快退按钮的动作面板中添加如下ActionScript:
on (release) {
if ((_root.music.position/_root.music.duration)>0.05) {
pos = _root.music.position/1000; //获取MP3的当前进度
_root.music.stop();
_root.music.start((pos-0.05*_root.music.duration/1000), 1);
//从当前进度快退5%开始播放
if (_root.music.getBytesTotal()>0) { //有声音载入时播放相关动画
_root.face.mcphone.gotoAndPlay(2);
_root.face.tyre.gotoAndPlay(2);
_root.scene.gotoAndPlay(2);
}
} else {
_root.music.start();
if (_root.music.getBytesTotal()>0) {
_root.face.mcphone.gotoAndPlay(2);
_root.face.tyre.gotoAndPlay(2);
_root.scene.gotoAndPlay(2);
}
}
}
(8)在暂停按钮的动作面板中添加如下ActionScript:
on (release) {
if (pause != 1) { //pause!=1表示播放状态,停止声音
_root.music.stop(); //停止声音和相关动画
_root.face.mcphone.gotoAndStop(1);
_root.face.tyre.gotoAndStop(1);
_root.scene.gotoAndStop(1);
pos = _root.music.position;
pause = 1; //标记暂停状态
} else { //pause==1表示暂停状态,播放声音
_root.music.start(pos/1000, 1); //在停止位置开始声音
if (_root.music.getBytesTotal()>0) { //有声音载入时播放相关动画
_root.face.mcphone.gotoAndPlay(2);
_root.face.tyre.gotoAndPlay(2);
_root.scene.gotoAndPlay(2);
}
pause = 0; //标记播放状态
}
}
(9)控制音量、声道和进度的游标都是内嵌了按钮的影片剪辑。在音量游标影片剪辑的动作面板中添加如下ActionScript:
onClipEvent (load) {
left = _x-100;
right = _x;
top = _y;
bottom = _y;
}
onClipEvent (enterFrame) {
_root.music.setVolume(_x-left); //将音量游标和标尺左端的距离作为音量大小
}
(10)在音量游标内的按钮的动作面板中添加如下ActionScript:
on (press) {
startDrag("", false, left, top, right, bottom); //限制游标的拖动范围
}
(11)在声道游标影片剪辑的动作面板中添加如下ActionScript:
onClipEvent (load) {
left = _x-50;
right = _x+50;
top = _y;
bottom = _y;
center = _x;
}
onClipEvent (enterFrame) {
_root.music.setPan((_x-center)*2); //将声道游标和标尺中点的距离作为声道值
}
on (release, releaseOutside) {
stopDrag();
}
(12)在声道游标内的按钮的动作面板中添加如下ActionScript:
on (press) {
startDrag("", false, left, top, right, bottom); //限制游标的拖动范围
}
on (release, releaseOutside) {
stopDrag();
}
(13)在进度游标影片剪辑的动作面板中添加如下ActionScript:
onClipEvent (load) {
source = _x;
left = _x;
top = _y;
right = _x+100;
bottom = _y;
}
onClipEvent (enterFrame) {
_x = source+100*(_root.music.position/_root.music.duration);
}
(14)在进度游标内的按钮的动作面板中添加如下ActionScript:
on (press) {
startDrag("", false, left, top, right, bottom);
}
on (release, releaseOutside) {
_root.music.stop();
_root.music.start(((_root.face._xmouse-source)/100*_root.music.duration/1000), 1);
stopDrag();
}
(15)在整个播放器影片剪辑的动作面板中添中如下ActionScript:
onClipEvent (load) {
days = new Array('SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT');
datetime = new Date(); //创建Date对象
}
onClipEvent (enterFrame) {
mymonth = datetime.getMonth()+1; //mymonth是显示月份的动态文本变量名
mydate = datetime.getDate(); //mydate是显示日期的动态文本变量名
day = datetime.getDay();
myday = days[day]; //myday是显示星期的动态文本变量名
myhour = datetime.getHours(); //myhour是显示小时的动态文本变量名
if (myhour<10) {
myhour = "0"+myhour;
}
myminute = datetime.getMinutes(); //myminute是显示分钟的动态文本变量名
if (myminute<10) {
myminute = "0"+myminute;
}
mysecond = datetime.getSeconds(); //mysecond是显示秒的动态文本变量名
if (mysecond<10) {
mysecond = "0"+mysecond;
}
delete datetime; //删除Date对象
datetime = new Date(); //获取新的系统时间
}
(16)在播放器影片剪辑中加入了一个透明度为0的按钮,在它的动作面板中添加如下ActionScript:
on (press) {
this.startDrag("true"); //按下鼠标时拖动播放器
}
on (release, releaseOutside) {
this.stopDrag(); //释放鼠标时停止拖动播放器
}
(17)按Ctrl+Enter键测试影片,效果如图14-5所示。

 

第15章 实现与服务器的交互

作为Macromedia公司的网页三剑客之一,Flash理所当然地在网页设计和网络运用方面占占据着重要的地位。不仅可以在网页中嵌入Flash动画,而且可以使用Flash制作网站片头、导航条,甚至是全Flash的网站。借助于ActionScript,Flash也具备与服务器的交互功能。优秀的服务器端程序与ActionScript的结合将使网页更加精彩。

15.1 简单链接
使用ActionScript可以将Flash影片链接到指定的网页,这与HTML中的<A HREF>标记类似。如在按钮中添加如下ActionScript:
on (release) {
getURL(" http://www.macromedia.com" ;);
}
无论该Flash影片是独立存在的还是嵌入在网页中,单击该按钮都将启动浏览器并打开通过getURL命令指定的页面,这里是Macromedia公司的主页。
getURL动作位于动作面板的“动作”/“浏览器/网络”目录。
除了使用getURL命令,也可以直接在动态文本中添加超链接,如为动态文本变量url添加链接如下所示:
url = "<A HREF=' http://www.macromedia.com& #39;>The Macromedia Homepage.</A>";
在动态文本框中将显示The Macromedia Homepage.它与网页中的<A HREF>标记类似,只是链接文字下面没有下划线。
除了可以链接到网络中的地址,getURL命令还可以用来打开计算机中的文件夹和文件,如通过单击按钮打开F盘:
on (release) {
getURL("file:///f:");
}
通过单击按钮打开文件:
on (release) {
getURL("file:///f:/music/Stronger.DAT");
}
15.2 指定打开链接的目标框架或窗口
使用getURL可以指定浏览器中用来打开链接的框架或窗口,getURL命令的第2个参数即用来指定目标框架或窗口的名称。
如Flash影片所在的网页是由两个框架构成的,Flash所在的框架名为Frame1,另一个框架名为Frame2,可以使用如下所示的ActionScript在框架Frame2中打开目标网页:
on (release) {
getURL(" http://www.macromedia.com" ;, "Frame2");
}
指定窗口的方式与此相同。
在ActionScript中有4个特殊的关键字用来指示浏览器执行特殊的操作,如下所示:
= _blank
在新窗口中打开目标页,该窗口将应用默认的浏览器设置。
= _parent
在当前框架的父级打开目标页。
= _top
在当前框架的顶级窗口中打开目标页,无论当前窗口由多少子框架构成,目标页都将取代框架而占据整个窗口。
= _self
使用当前窗口或框架打开目标页。当getURL命令省略第2个参数时即默认此方式。
如在新窗口中打开目标页的ActionScript如下所示:
on (release) {
getURL(" http://www.macromedia.com" ;, "_blank");
}
如果要自定义浏览器中新窗口的大小或设置,你将需要用到JavaScript。
15.3 LoadVars对象
Flash MX版本提供了新增的LoadVars对象使你可以实现Flash与服务器的交互。
LoadVars 对象是 loadVariables 动作的替代方法,用于在 Flash 影片和服务器之间传输变量。
可使用 LoadVars 对象在下载时获取错误信息、进度指示和流数据。LoadVars 对象的工作原理非常类似于 XML 对象;它使用方法 load、send 和 sendAndLoad 与服务器进行通讯。LoadVars 对象和 XML 对象的主要差别在于 LoadVars 传输动作脚本的名称和值对,而不是 XML 对象中存储的 XML DOM 树。
LoadVars 对象与 XML 对象遵循相同的安全限制。
15.3.1 从服务器下载数据
和其他对象一样,在使用LoadVars对象之前必须使用构造函数创建一个LoadVars对象的实例,如下所示:
myVars = new LoadVars();
要从服务器获取数据可以使用命令load,只需在load命令中指定要下载据的链接地址,如下所示:
myVars.load("myURL.txt");
从这里看来,LoadVars对象的load命令和LoadVariables命令很相似,但是LoadVariables命令不能区别文本中的不同变量,而在load命令中可以指定要获取数据的变量,如文本url.txt中有如下内容:
ID=thyme&Password=cd99
在Flash文件的第1帧动作面板中添加如下ActionScript:
myVars = new LoadVars();
myVars.load("url.txt");
在第40帧的动作面板中添加如下ActionScript:
stop();
loadVariables("url.txt", _root);
_root.varID = myVars.ID;
_root.varPA = myVars.Password;
其中,第40帧的第1个动态文本变量名为ID,第2个动态文本变量名为varID,第3个动态文本变量名为varPA。
需要说明的是,与loadVariables命令相同,load命令指定的链接文件也必须与Flash的播放文件在同一个文件目录下面。
15.3.2 向服务器上传数据
使用send命令可以向服务器上传数据,如下所示:
myVars = new LoadVars();
myVars.ID = "thyme";
myVars.Password = cd99;
myVars.send("mypage.asp", "_self");
以上的脚本创建一个LoadVars对象myVars,然后分别设置两个属性ID和Password,最后将该对象发送到服务器的mypage.asp页中。
参数_self表示将使用上传的变量从服务器获取信息以刷新当前页面。
使用sendAndLoad命令不仅可以上传数据,而且可以获取服务器的响应信息,如下所示:
mySendVars = new LoadVars();
myLoadVars = new LoadVars();
mySendVars.ID = "thyme";
mySendVars.Password = cd99;
mySendVars.sendAndLoad("mypage.asp", myLoadVars);
其中创建了两个LoadVars对象,myLoadVars作为sendAndLoad命令的第2个参数用于存放来自服务器的响应。
15.3.3 下载状态
使用load、send、sendAndLoad命令下载和上传数据有一定的速度限制,这种速度与客户端和服务器的数据传输速率有关,但是无论如何都不是刚一执行命令就能马上完成。如上面的例子,其中在第1帧执行load命令,在第40帧才使用脚本将其中的数据在动态文本中显示出来;如果只有1帧,在执行load命令后马上使用脚本为动态文本变量赋值,并不能实现我们预期的效果。
为了避免被动地等待数据传输,LoadVars对象提供了检测数据下载状态的办法。
使用getBytesLoaded和getBytesTotal方法可以了解数据下载的进度,传输的数据量小并且网络速度也并不是很慢时这两种方法并不能发挥明显的作用。如果要解决上例中的问题,可以定义一个在数据下载完成时执行的函数,当数据完全传输成功时,系统会自动启动该函数。
如要将文件load.fla的第40帧合并到第1帧,如果使用如下的ActionScript,结果如图15-3所示。
stop();
myVars = new LoadVars();
myVars.load("url.txt");
loadVariables("url.txt", _root);
_root.varID = myVars.ID;
_root.varPA = myVars.Password;

如果将其中的脚本改写成如下所示,我们将得到正确的结果,如图15-4所示:
stop();
loadVariables("url.txt", _root);
myVars = new LoadVars();
myVars.load("url.txt");
myVars.onLoad = function() {
_root.varID = myVars.ID;
_root.varPA = myVars.Password;
};

仅仅完成从服务器下载和向服务器上传数据是不够的,要用Flash更强大的应用程序就得编写相应的服务器端脚本,如前面提到的mypage.asp就是用ASP(Active Sever Pages)语言编写的动态页面。编写服务器端脚本的语言很多,如PHP、CGI、Perl等,限于篇幅,在此不予详细讲解。

 

第16章 XML运用

XML(eXtensible Markup Language可扩展置标语言),它是有别于HTML(Hyper Text Markup Language超文本置标语言)的一种数据表示规范。由于它极大的灵活性和方便性,在存储和表示数据方面占据了巨大的优势。
ActionScript中的XML对象为你提供了访问XML文档的途径,使用点语法和XML对象的属性可以方便地访问XML文档(既可以是存储XML数据的文本文档,也可以是XML格式的文档)中的具体数据,并可以在Flash中将外部XML文档中的数据显示出来。

16.1 XML基础
XML与HTML有相似之处,因为它们都使用标签(tag)。但是HTML中的标签都是HTML的语法所预定好的,如<font></font>表示字体,<br>表示换行等;而XML中的标签则可以由用户根据需要、习惯和爱好自由指定,如下所示是一个XML的例子:
<student>
<name>Thyme</name>
<age>18</age>
<score>
<English>94</English>
<Physics>86</Physics>
<Chemistry>99</Chemistry>
</score>
<grade>B</grade>
</student>
上例的XML文档定义了一个student对象,在student对象下面包含4组信息,分别是name、age、score和grade,在score下面又分为English、Physics、Chemistry这3类,以上这些成对出现的标志即是XML的标签,标签又称为XML的元素(element)或节点(node)。每对节点之间包含与该节点相对应的数据,这些数据又称为文本节点(text node)。
使用XML表示的数据结构一目了然,这也是它之所以深受人们宠爱的原因之一。在Flash中使用XML对象可以方便地解析XML的数据结构,以访问需要的节点或数据。
XML的另一大优点就是可以使用简单的文本编辑器进行编辑,程序员可以很容易地编写出访问XML格式数据的程序。这也为使用Flash制作与服务器交互的影片提供了一条捷径。
16.2 XML对象
同ActionScript的其他对象一样,要使用XML对象,就得先创建XML对象的实例,其方法如下:
myXML = new XML();
XML对象提供了众多的属性、方法和事件,下面重点介绍常用的几种。
16.2.1 load方法
XML的load方法用于从指定的URL中加载XML文档,并使用下载的XML数据替换指定XML对象的内容。使用load方法加载的XML文档必须与Flash影片处于相同的文件夹中。如下所示的ActionScript创建并从外部文本文档中加载XML对象:
myXML = new XML();
myXML.load("XMLData.txt");
如下所示的ActionScript创建并从外部XML文档中加载XML对象:
myXML = new XML();
myXML.load("XMLData.xml");
和LoadVars.load方法类似,使用XML.load命令后并不能立即将外部文档中的数据加载到影片中,如果直接引用文档中的数据可能会得不到需要的结果。要判断XML文档是否已经加载到影片中,可以使用下面要介绍的onLoad事件。
16.2.2 onLoad事件
当从服务器上接收XML文档时,由Flash Player调用XML的onLoad事件。调用onLoad事件时自动返回一个参数success,如果成功地收到XML文档,则success参数为true;如果未收到该文档,或从服务器上接收响应时出现错误,则success参数为false。
onLoad事件的使用方法如下所示:
myXML = new XML();
myXML.load("XMLData.txt");
myXML.onLoad = function() {
if (success == true) {
trace("XML is successfully loaded");
} else {
trace("Something is wrong with the XML document");
}
};
16.2.3 childNodes属性
XML的childNodes属性返回指定XML对象的子级的数组,数组中的每个元素都是对表示子节点的XML对象的引用,也就是说childNodes属性将XML对象当前级的子级节点作为一个数据返回。与数据一样,使用方括号可以访问数据的每一个元素。
例如外部文档中有图16-1所示结构图的XML对象,先将其加载到影片中的XML对象中:
myXML = new XML();
myXML.load("XMLData.xml");
myXML.onLoad = function(success) {
if (success == true) {
trace(myXML.childNodes[0]);
}
};
运行以上脚本,输出窗口中将显示整个XML对象
将上面脚本中的trace语句换成如下所示:
trace(myXML.childNodes[0].childNodes[0]);
运用脚本,奇怪,输出窗口中没有显示。其实并不是没有显示,而是因为<student>后面有一个换行,Flash没能识别这个换行,而是将一个空行也作为XML对象的一个节点了。如果要验证,可以运行以下脚本:
trace(myXML.childNodes[0].childNodes[1]);
输出窗口中显示:
<name>Thyme</name>
如果Flash Player不能识别空格和空行,那么就不能把XML文档写成很有层次的格式,也就不方便我们阅读了。事实上,不用担心,下一个属性将帮助你解决这个问题。
16.2.4 ignoreWhite属性
ignoreWhite属性的默认设置为false,当设置为true时,在分析过程中将放弃仅包含空白的文本节点。要解决前面遇到的问题,只需要将XML对象的ignoreWhite属性设置为true即可。
在上例中使用如下所示的ActionScript将在输出窗口中返回<name>Thyme</name>:
myXML = new XML();
myXML.load("XMLData.xml");
myXML.ignoreWhite = true;
myXML.onLoad = function(success) {
if (success == true) {
trace(myXML.childNodes[0].childNodes[0]);
}
};
如果要返回<Physics>86</Physics>就需要如下的ActionScript:
trace(myXML.childNodes[0].childNodes[2].childNodes[1]);
如何才能返回Physics字段中的86呢?下面的ActionScript可以吗:
trace(myXML.childNodes[0].childNodes[2] .childNodes[1].childNodes[0]);
上面的脚本的确是返回了86,但事实上,它返回的是86这个节点,而不是这个节点中的文本。要得到文本节点中的文本字段,就需要使用nodeValue属性。
16.2.5 nodeValue属性
nodeValue属性返回XML对象的节点值。如果XML对象为文本节点,则nodeValue为该节点的文本;如果该XML对象是XML元素,则其nodeValue为null。
要得到上例中的文本86,可以使用如下所示的ActionScript:
trace(myXML.childNodes[0].childNodes[2].childNodes[1].childNodes[0].nodeValue);
既然XML元素和XML的文本节点是有区别的,就有必要将这两种类型的节点区别开来。
16.2.6 nodeType属性
nodeType是一个只读属性,值为1表示XML元素,为3表示文本节点。如上例中,使用以下脚本将分别返回1和3。
trace(myXML.childNodes[0].childNodes[2].childNodes[1].nodeType);
trace(myXML.childNodes[0].childNodes[2].childNodes[1].childNodes[0].nodeType);
16.2.7 nodeName属性
与节点密切相关的还有一个nodeName属性。nodeName属性返回XML对象的节点名称,如果该XML对象是一个XML元素(nodeType==1),则nodeName是表示XML文件中节点的标签名称;如果该XML对象为文本节点(nodeType==3),则nodeName为null。如上例中,使用以下脚本将分别返回Physics和null:
trace(myXML.childNodes[0].childNodes[2].childNodes[1].nodeName);
trace(myXML.childNodes[0].childNodes[2].childNodes[1].childNodes[0].nodeName);
16.2.8 status属性
如果从外部加载进来的XML文档有漏洞,在Flash影片中引用时肯定会出现问题。XML对象的status属性可以帮助检查XML对象是否完整和存在缺陷。调用status属性将返回一个数值,该数值的不同状态分别表示不同的含义,如下所示:
= 0 没有错误;成功地完成了分析。
= -2 一个CDATA部分没有正确结束。
= -3 XML声明没有正确结束。
= -4 DOCTYPE声明没有正确结束。
= -5 一个注释没有正确结束。
= -6 一个XML元素有格式错误。
= -7 内存不足。
= -8 一个属性值没有正确结束。
= -9 一个开始标记没有匹配的结束标记。
= -10 遇到一个没有匹配的开始标记的结束标记。
通过分析status属性的不同值,可以对相应的XML文档作有针对性的检查和修改,直到没有错误为止。
16.3 练习:用表单显示XML文档内容
本练习的目的是使用表单加载和显示XML文档的内容,以对XML对象的各种常用属性、方法和事件有进一步的了解。本练习的源文件为XML.fla。在同一文件夹中包含一个XML格式的文档,其中的内容如下所示:
<form>
<formname>Author's Information</formname>
<Name>
<firstname>Thyme</firstname>
<familyname>CD</familyname>
</Name>
<IDNo.>510228198111079090</IDNo.>
<Address>
<mailID>610031</mailID>
<Street>New 2 Fu Qing West Road</Street>
<City>Chengdu</City>
<Country>China</Country>
</Address>
<Tel>
<Home>028-87732901</Home>
<Move>028-81822013</Move>
</Tel>
<E-mail>chendong2000will@sina.com</E-mail>
</form>
在文件XML.fla的第一帧中添加了table0~table17共18个动态文本,在帧动作面板中添加了如下所示的ActionScript:
stop();
myXML = new XML();
myXML.ignoreWhite = true;
myXML.load("information.xml");
myXML.onLoad = function() {
if (myXML.status == 0) {
t0 = myXML.childNodes[0].childNodes[0].childNodes[0].nodeValue;
t1 = myXML.childNodes[0].childNodes[1].nodeName;
t2 = myXML.childNodes[0].childNodes[1].childNodes[0].childNodes[0].nodeValue;
t3 = myXML.childNodes[0].childNodes[1].childNodes[1].childNodes[0].nodeValue;
t4 = myXML.childNodes[0].childNodes[2].nodeName;
t5 = myXML.childNodes[0].childNodes[2].childNodes[0].nodeValue;
t6 = myXML.childNodes[0].childNodes[3].nodeName;
t7 = myXML.childNodes[0].childNodes[3].childNodes[3].childNodes[0].nodeValue;
t8 = myXML.childNodes[0].childNodes[3].childNodes[2].childNodes[0].nodeValue;
t9 = myXML.childNodes[0].childNodes[3].childNodes[1].childNodes[0].nodeValue;
t10 = myXML.childNodes[0].childNodes[3].childNodes[0].childNodes[0].nodeValue;
t11 = myXML.childNodes[0].childNodes[4].nodeName;
t12 = myXML.childNodes[0].childNodes[4].childNodes[0].nodeName;
t13 = myXML.childNodes[0].childNodes[4].childNodes[0].childNodes[0].nodeValue;
t14 = myXML.childNodes[0].childNodes[4].childNodes[1].nodeName;
t15 = myXML.childNodes[0].childNodes[4].childNodes[1].childNodes[0].nodeValue;
t16 = myXML.childNodes[0].childNodes[5].nodeName;
t17 = myXML.childNodes[0].childNodes[5].childNodes[0].nodeValue;
} else {
gotoAndStop("error");
}
};
第2帧用于显示XML文档加载出错的信息。将第2帧的帧标签设为error,在其中添加一个按钮“get more information”,在该按钮的动作面板中添加如下ActionScript:
on (release) {
gotoAndStop("errorinfor");
switch (myXML.status) {
case -2 :
errorinfor = "A CDATA has no correct ending";
break;
case -3 :
errorinfor = "XML declaration has no correct ending";
break;
case -4 :
errorinfor = "DOCTYPE declaration has no correct ending";
break;
case -5 :
errorinfor = "A comment has no correct ending";
break;
case -6 :
errorinfor = "An XML node has wrong format";
break;
case -7 :
errorinfor = "Memory of computer is not enough";
break;
case -8 :
errorinfor = "An attibute has no correct ending";
break;
case -9 :
errorinfor = "A beginning tag without an ending one";
break;
case -10 :
errorinfor = "An ending tag without a beginnig one";
break;
}
}
将第3帧的帧标签设为errorinfor,并在第3帧中添加一个名为errorinfor的动态文本。当单击“get more information”按钮时,将在第3帧中显示相关的出错信息。
XML文档无误时的Flash表单如图16-3所示。试着改一下XML文档的内容(以记事本方式打开information.xml进行修改),此时的Flash影片如图16-4所示。单击“get more information”,

 

第17章 Flash UI组件

Flash MX中新增了7种内置组件(Flash UI Components),它们是PushButton、CheckBox、RadioButton、ListBox、ComboBox、ScrollPane、ScrollBar。要将这些组件添加到影片中,只需要在组件面板中双击相应的组件或在组件上按下鼠标将其拖动到场景中。

17.1 组件面板
选择“窗口”→“组件”命令或按快捷键Ctrl+F7即可打开Flash MX的组件面板,如图17-1所示。
在组件面板中双击组件或是按下鼠标左键拖动组件都可以将组件添加到场景中。添加内置组件后,Flash的库面板中会添加一个名为Flash UI Components的组件夹,如果添加了不止一种组件,它们都将自动保存在这个组件夹中,所以不会给你带来多大麻烦。
17.2 PushButton
在场景中添加了PushButton后,选中PushButton,它的属性面板如图17-3所示。

图17-3 PushButton的属性面板
单击属性面板右下角的“属性”按钮,属性面板将变成如图17-4所示。再单击“参数”按钮,属性面板将切换回原来的状态。

图17-4 单击“属性”按钮后的效果
在属性面板中PushButton有两个参数,Label即是PushButton的标签,即显示在按钮上的文字,默认的文字是Push Button。在Label栏单击,Label后的文本框变成可改写的,在其中输入要显示在按钮上的文字。Click Handler参数表示单击PushButton时要执行的函数,该函数必须与PushButton在同一条时间轴中。即如果PushButton位于主场景中,则它的事件处理函数应该在主时间轴的关键帧中。
在<实例名称>文本框中可以为PushButton命名,它将作为PushButton的name属性。单击PushButton时,name属性将作为参数传递给Click Handler指定的单击事件处理函数。
与用户创建的按钮一样,PushButton也可以使用按钮的on事件处理函数。
PushButton的使用方法见PushButton.fla。其中的函数如下所示:
function PushButtonClick(xbutton) {
trace(xbutton._name);
}
在场景中添加了3个PushButton,将Label分别设为“是”、“否”和“取消”,将Click Handler都设为PushButtonClick,将实例名称分别设为yes、no和cancel。按Ctrl+Enter键测试影片,分别在3个按钮上单击,输出窗口中将相应地显示yes、no和cancel。

17.3 CheckBox
CheckBox就是我们平常所见的复选框,它有选中和未选中两种状态
CheckBox的Label参数与PushButton类似,Initial Value参数是CheckBox的初始状态,false表示未选中,true表示选中
Label Placement参数决定Check Box的标签(Label)位于复选框的左边还是右边,它有两个值right和left,默认为right.
Change Handler参数与PushButton的Click Handler属性类似,表示改变CheckBox的状态时要调用的事件处理函数,该函数也必须与CheckBox位于相同的时间轴中。
改变CheckBox的状态时,它的实例名称将作为参数传递给事件处理函数,在编写脚本时可以利用这个属性。
CheckBox的使用方法见CheckBox.fla,其中用于CheckBox的事件处理函数如下所示:
function CheckBoxChange(xCheckBox) {
if (xCheckBox.getValue() == true) {
trace("You like "+xCheckBox._name);
} else {
trace("You dislike "+xCheckBox._name);
}
}
getValue方法用来获取CheckBox的状态,CheckBox还有getLabel以及setValue、setLabel等方法,在此不再详述。
17.4 RadioButton
RadioButton即常说的单选按钮或单选项,它与CheckBox类似,但是在同一组RadioButton中只能有一个为选中状态,而一组CheckBox中的任意一个都可以为选中状态。
RadioButton的使用方法见RadioButton.fla,其中的函数如下所示:
function RadioButtonChange(xRadioButton) {
trace("You like "+xRadioButton.getData());
}
17.5 ListBox
ListBox即列表框,使用ListBox可以将多个选项综合在一个列表框中,从而代替CheckBox和RadioButton行使它们的功能。
选中Labels或Data栏再单击鼠标,将打开如图17-11所示的值面板,单击 和 按钮可以添加或删除项目,单击 和 按钮可以将项目向下或向下移动。
在值面板中添加完项目后,单击“确定”按钮即可。
Select Multiple参数决定ListBox中的项目是否可以多选,为false时不能多选,相当于一组RadioButton;为true时可以多选,相当于一组CheckBox。
使用getValue方法返回有关列表框中当前选定项的信息。如果该项目没有指定的Data,则此方法返回该项目的Label;如果该项目有关联的Data,则此方法返回该Data。在单选列表框中使用getSelectedItem方法可以将选定的项目作为一个具有Label和Data属性的对象返回,在多选列表框中使用getSelectedItems方法可以将选定的项目作为一个具有Label和Data属性的数组返回。ListBox的使用方法见ListBox.fla。其中的函数如下所示:
function ListBoxChange(xListBox) {
trace(xListBox.getSelectedItem().Label+":"+xListBox.getSelectedItem().Data);
}
17.6 ComboBox
ComboBox即组合框,也即下拉列表框。既然称为组合框,ComboBox是由一个文本框和一个列表框组合起来的,平常只显示文本框,单击下拉箭头可以展开列表框,因此它比ListBox要节省许多空间。
它的第1个参数Editable,表示ComboBox是否可编辑。当Editable为false时ComboBox中的方框是不可编辑的;当Editable为true时ComboBox中的方框相当于一个输入文本框,你可以在其中输入字符,也可以在其下拉列表中进行选择。
ComboBox的Labels和Data参数与ListBox类似。Row Count参数表示ComboBox的下拉列表中可以直接显示的项数,超过这个项数就需要使用滚动条查看。默认的Row Count为8,你也可以根据需要进行修改。
ComboBox的使用方法见ComboBox.fla,其中的函数如下:
function ComboBoxChange(xComboBox) {
trace(xComboBox.getValue()+":"+xComboBox.getSelectedItem().Data);
}
17.7 ScrollPane
ScrollPane组件包含水平滚动条、垂直滚动条和视图区。
ScrollPane最重要的参数是Scroll Content,它代表视图区中要显示的影片剪辑的链接名称,即在库面板中元件的链接字段中的链接标识符。运行影片时,Scroll Content参数指向的影片剪辑将加载到视图区中显示。
Horizontal Scroll和Vertical Scroll参数都具有3个可选值:auto、true和false。当值为auto(自动)时,将根据加载的影片剪辑的实际大小是否超出视图区的边界来决定水平和垂直滚动的条的显示与否;当值为true时永远显示对应的滚动条;当值为false时不显示滚动条。
Drag Content参数决定视图区中的内容是否可以使用鼠标进行拖动,它有两个值:true和false。
除了在Scroll Content参数中指定要加载的影片剪辑外,还可以使用loadScrollContent命令将外部的swf文件加载到ScrollPane的视图区中。ScrollPane的使用方法见ScrollPane.fla,其中有两个ScrollPane,一个使用Scroll Content参数加载库中的影片剪辑graphic,另一个使用loadScrollContent命令将外部的pic.swf文件加载到视图区中,其脚本如下所示:
myScrollPane.loadScrollContent("pic.swf");

17.8 ScrollBar

ScrollBar即滚动条,它可以添加到动态文本或输入文本中。其属性面板如图17-17所示。

图17-17 ScrollBar的属性面板
Target TextField参数指定与ScrollBar相组合的动态文本或输入文本的实例名称,将ScrollBar拖动到文本框要添加滚条的边框一侧,Target TextField参数的值将自动改变成与文本实例的名称相一致。
Horizontal参数决定ScrollBar是水平还是垂直的,为false时是垂直滚动条,为true时是水平滚动条。
ScrollBar的使用见ScrollBar.fla。

 

第18章 用ActionScript画图

Flash MX ActionScript的绘画方法位于动作面板的“对象”/“影片”/“MovieClip”/“绘画方法”目录下面。使用ActionScript的绘画方法可以定义线条样式、画直线、曲线、对图形进行填充以及清除所画图形等操作。

18.1 动态创建影片剪辑
由于绘画方法包含在影片剪辑中,所以在使用绘画方法前要创建影片剪辑。使用MovieClip的createEmptyMovieClip方法可以动态地创建影片剪辑,如下所示:
_root.createEmptyMovieClip("MovieClipName", depth);
其中,MovieClipName是创建的影片剪辑实例名,depth是创建的影片剪辑所在的深度级别。
18.2 绘画方法
18.2.1 lineStyle
MovieClipName.lineStyle ([thickness[,rgb[,alpha]]])
linStyle命令定义将要绘制的线条的样式,其中,参数thickness定义线条的粗细,rab参数定义线条的颜色,alpha参数定义线条的透明度。如:
lineStyle(0, 0x000000, 100); //定义极细线条,颜色为黑色,不透明
lineStyle(2, 0xFF0000, 50); //定义线条宽度为2,颜色为红色,透明为50%
定义了线条样式后即可以使用绘线命令绘制线条,绘制的线条都将保持与lineStyle命令所定义一致的样式,直到使用新的lineStyle命令为止。
18.2.2 moveTo
MovieClipName.moveTo (x,y)
moveTo命令将当前绘画位置移到指定的坐标点(x,y)。
moveTo命令一般用于新起一点开始画线。
18.2.3 lineTo
MovieClipName.lineTo (x,y)
使用当前线条样式从当前绘画位置向(x,y)绘制直线;当前绘画位置随后被设置为(x,y)。
18.2.4 curveTo
MovieClipName.curveTo (controlX,controlY,anchorX, anchorY)
使用由(controlX,controlY)指定的控制点,以当前的线条样式绘制从当前绘画位置到(anchorX,anchorY)的曲线。当前的绘画位置随后设置为(anchorX,anchorY)。使用curveTo命令最关键的就是控制点的确定。控制点相当于是所绘曲线起始点和终点切线的交点,
18.2.5 beginFill
MovieClipName.beginFill ([rgb[,alpha]])
beginFill命令表示填充的开始,参数rgb表示要用于填充的颜色,alpha表示透明度。在使用beginFill命令后所绘制的闭合路径将自动以beginFill命令指定的颜色和颜色进行填充。
18.2.6 beginGradientFill
MovieClipName.beginGradientFill (fillType, colors, alphas, ratios, matrix)
beginGradientFill用于在闭合路径中填充渐变色,参数fillType有两个值:linear表示线性渐变,radial表示放射渐变。colors是一个数组,包括要在渐变中使用的RGB十六进制颜色值。alphas也是一个数组,包括与colors数组中颜色相对应的Alpha值;有效值为0~100。如果该值小于0,则Flash使用0。如果该值大于100,则Flash使用100。ratios是颜色配额的数组;有效值为0~255。该值按100%定义了对颜色进行采样处的宽度的百分比。matrix 一个变形矩阵,是带有下列两组属性之一的一个对象:
= a、b、c、d、e、f、g、h、i,它们用于描述下列形式的 3×3 矩阵:
a b c
d e f
g h i
如果matrixType属性不存在,则其余参数都是必需的;如果缺少其中任何一个则该函数会失败。该矩阵缩放、平移、旋转和倾斜在(-1,-1)和(1,1)处定义的单位渐变。
= matrixType、x、y、w、h、r。
这些属性表示下列含义:matrixType 是字符串box、x是相对于该渐变左上角父级剪辑的注册点的水平位置,y是相对于该渐变左上角父级剪辑的注册点的垂直位置,w是渐变的宽度,h是渐变的高度,r是渐变的旋转角度(以弧度为单位)。
18.2.7 endFill
MovieClipName.endFill()
对调用beginFill或beginGradientFill方法以来添加的线条或曲线应用填充。Flash使用的是对beginFill或beginGradientFill的上一次调用中指定的填充。如果当前的绘画位置不等于moveTo方法中指定的上一个位置,而且定义了填充,则用线条闭合该路径,然后进行填充。
18.2.8 clear
MovieClipName.clear()
删除与影片剪辑关联的所有绘画命令。用Flash绘画工具绘制的形状和线条不受影响。调用clear方法还会删除当前的线条样式。
18.3 练习:全脚本的图形
使用绘图方法绘制全脚本的图形不难,主要是工作量比较大,要求细心。一般来说完全使用ActionScript命令绘制复杂图形的意义不是很大,作为了解已经足够了。
下面给出文件draw.fla的所有源程序,供你参考。其中主要用到的绘图方法有lineStyle、moveTo、lineTo和curveTo,没有用到的方法请自己研究和练习。

_root.createEmptyMovieClip("girl", 1);
with (_root.girl) {
lineStyle(0, 0x000000, 100);
beginFill(0x000000, 100);
moveTo(138, 164);
curveTo(119, 160, 98, 165);
curveTo(120, 155, 138, 164);
moveTo(156, 166);
curveTo(166, 162, 174, 164);
lineTo(174, 161);
curveTo(164, 160, 156, 166);
endFill();
lineStyle(2, 0x000000, 100);
moveTo(133, 178);
curveTo(116, 166, 104, 183);
moveTo(132, 181);
curveTo(116, 169, 104, 184);
moveTo(132, 184);
curveTo(117, 170, 104, 184);
moveTo(128, 193);
curveTo(119, 197, 109, 193);
moveTo(126, 179);
curveTo(130, 191, 121, 195);
moveTo(117, 195);
curveTo(106, 184, 116, 175);
lineStyle(0, 0x000000, 100);
moveTo(115, 179);
curveTo(118, 180, 118, 183);
curveTo(116, 185, 113, 183);
curveTo(114, 190, 119, 191);
curveTo(125, 190, 125, 185);
curveTo(124, 177, 115, 179);
lineStyle(2, 0x000000, 100);
moveTo(151, 185);
curveTo(151, 177, 160, 173);
curveTo(168, 171, 173, 176);
moveTo(154, 180);
curveTo(162, 170, 171, 178);
moveTo(163, 174);
curveTo(170, 175, 170, 182);
moveTo(155, 192);
curveTo(163, 195, 167, 191);
moveTo(160, 175);
curveTo(153, 181, 155, 189);
curveTo(157, 192, 161, 192);
curveTo(171, 188, 163, 176);
lineStyle(0, 0x000000, 100);
moveTo(160, 180);
curveTo(162, 182, 161, 183);
curveTo(159, 184, 158, 182);
curveTo(156, 187, 160, 189);
curveTo(164, 189, 164, 185);
curveTo(164, 180, 160, 180);
lineStyle(2, 0x000000, 100);
moveTo(148, 185);
curveTo(147, 195, 153, 203);
curveTo(147, 207, 147, 209);
moveTo(130, 219);
lineTo(152, 218);
lineStyle(3, 0x000000, 40);
moveTo(133, 225);
lineTo(143, 225);
lineStyle(1, 0x000000, 100);
moveTo(174, 145);
curveTo(176, 157, 175, 172);
curveTo(173, 181, 172, 186);
lineTo(169, 212);
curveTo(169, 217, 164, 224);
lineTo(148, 242);
curveTo(144, 246, 135, 246);
curveTo(112, 242, 96, 230);
moveTo(71, 168);
curveTo(68, 164, 63, 164);
curveTo(58, 164, 55, 172);
curveTo(56, 191, 68, 204);
lineTo(74, 206);
lineStyle(1, 0x000000, 60);
moveTo(70, 174);
curveTo(67, 170, 63, 169);
curveTo(54, 174, 62, 185);
curveTo(68, 200, 72, 192);
moveTo(71, 180);
curveTo(71, 177, 68, 177);
curveTo(65, 177, 65, 180);
curveTo(66, 185, 64, 189);
curveTo(70, 200, 72, 189);
curveTo(67, 184, 71, 181);
lineStyle(1, 0x000000, 60);
moveTo(47, 151);
curveTo(55, 93, 113, 85);
lineTo(115, 87);
lineTo(116, 85);
curveTo(170, 92, 195, 130);
curveTo(207, 158, 194, 164);
curveTo(207, 152, 185, 123);
curveTo(203, 150, 189, 169);
curveTo(193, 150, 186, 138);
curveTo(197, 169, 179, 179);
curveTo(190, 174, 184, 145);
moveTo(176, 127);
curveTo(190, 165, 178, 174);
curveTo(184, 159, 178, 137);
curveTo(182, 156, 173, 169);
curveTo(179, 155, 175, 139);
moveTo(171, 123);
curveTo(181, 153, 164, 167);
curveTo(176, 146, 168, 127);
curveTo(175, 149, 159, 160);
curveTo(171, 141, 166, 129);
moveTo(161, 113);
curveTo(175, 141, 144, 164);
curveTo(161, 151, 161, 128);
moveTo(158, 127);
curveTo(159, 151, 143, 164);
curveTo(157, 147, 155, 119);
curveTo(152, 144, 120, 157);
curveTo(157, 136, 152, 106);
moveTo(150, 115);
curveTo(146, 139, 130, 150);
curveTo(140, 140, 147, 117);
curveTo(132, 149, 113, 153);
moveTo(145, 121);
curveTo(139, 132, 126, 141);
curveTo(116, 154, 97, 160);
moveTo(118, 141);
curveTo(103, 156, 98, 156);
moveTo(118, 141);
curveTo(105, 149, 98, 155);
curveTo(87, 162, 70, 163);
moveTo(101, 156);
curveTo(94, 163, 72, 163);
moveTo(71, 164);
curveTo(72, 222, 105, 318);
moveTo(74, 164);
curveTo(74, 185, 78, 205);
moveTo(77, 164);
curveTo(75, 194, 88, 241);
moveTo(80, 165);
curveTo(90, 245, 101, 292);
moveTo(72, 187);
curveTo(73, 225, 80, 250);
moveTo(82, 165);
curveTo(82, 210, 103, 259);
moveTo(85, 164);
lineTo(84, 193);
moveTo(90, 162);
lineTo(85, 171);
moveTo(95, 162);
lineTo(84, 177);
moveTo(172, 183);
curveTo(180, 247, 187, 263);
curveTo(200, 294, 195, 334);
moveTo(171, 200);
curveTo(174, 230, 182, 258);
moveTo(171, 212);
curveTo(170, 226, 183, 274);
curveTo(196, 314, 190, 331);
moveTo(168, 219);
curveTo(168, 234, 176, 263);
moveTo(165, 224);
lineTo(168, 242);
moveTo(163, 227);
curveTo(161, 251, 184, 296);
moveTo(166, 240);
curveTo(170, 253, 171, 268);
moveTo(173, 261);
curveTo(175, 272, 180, 281);
curveTo(188, 295, 189, 330);
lineStyle(2, 0x000000, 100);
moveTo(68, 165);
lineTo(75, 154);
curveTo(68, 155, 62, 150);
curveTo(60, 150, 55, 154);
lineTo(50, 155);
lineTo(46, 163);
curveTo(49, 163, 50, 161);
curveTo(55, 162, 57, 166);
curveTo(62, 162, 68, 165);
moveTo(47, 159);
lineTo(58, 159);
curveTo(58, 156, 55, 157);
moveTo(44, 154);
lineTo(39, 148);
lineTo(18, 153);
curveTo(20, 160, 14, 167);
lineTo(30, 161);
curveTo(38, 164, 43, 163);
curveTo(40, 156, 44, 154);
moveTo(42, 157);
lineTo(36, 159);
lineTo(30, 157);
moveTo(44, 154);
curveTo(50, 150, 52, 153);
moveTo(44, 164);
curveTo(38, 167, 32, 166);
lineTo(22, 170);
lineTo(14, 170);
lineTo(4, 177);
curveTo(15, 179, 13, 191);
curveTo(22, 173, 43, 166);
curveTo(53, 182, 41, 203);
curveTo(53, 195, 62, 209);
lineTo(61, 196);
moveTo(57, 168);
curveTo(50, 169, 48, 163);
lineStyle(1, 0x000000, 100);
moveTo(31, 171);
curveTo(13, 201, 21, 210);
moveTo(37, 168);
curveTo(15, 204, 24, 214);
moveTo(31, 187);
curveTo(20, 213, 31, 218);
moveTo(35, 195);
curveTo(27, 225, 37, 224);
moveTo(34, 206);
curveTo(35, 224, 40, 222);
moveTo(44, 167);
curveTo(33, 221, 44, 225);
moveTo(41, 209);
curveTo(42, 228, 52, 228);
moveTo(47, 199);
curveTo(43, 228, 57, 227);
moveTo(49, 199);
curveTo(50, 226, 60, 228);
curveTo(71, 227, 66, 202);
moveTo(64, 200);
curveTo(62, 244, 54, 201);
curveTo(61, 240, 60, 204);
lineStyle(2, 0x000000, 100);
moveTo(189, 169);
curveTo(192, 166, 195, 169);
curveTo(199, 174, 206, 176);
curveTo(196, 181, 196, 191);
curveTo(190, 178, 181, 179);
curveTo(188, 182, 188, 186);
curveTo(189, 189, 194, 188);
moveTo(187, 173);
lineTo(193, 175);
moveTo(197, 184);
lineTo(208, 189);
lineTo(204, 193);
curveTo(199, 190, 189, 205);
curveTo(188, 192, 184, 190);
curveTo(182, 189, 182, 183);
curveTo(179, 182, 180, 179);
lineStyle(1, 0x000000, 100);
moveTo(198, 193);
curveTo(207, 207, 193, 216);
moveTo(194, 203);
curveTo(195, 215, 188, 221);
moveTo(189, 204);
curveTo(192, 214, 186, 225);
curveTo(183, 227, 178, 224);
moveTo(180, 181);
curveTo(178, 186, 181, 191);
curveTo(187, 210, 182, 224);
moveTo(177, 181);
curveTo(176, 189, 180, 198);
curveTo(186, 213, 179, 223);
moveTo(181, 202);
curveTo(181, 219, 177, 218);
moveTo(176, 182);
curveTo(178, 199, 174, 205);
lineStyle(2, 0x000000, 100);
moveTo(80, 248);
curveTo(74, 248, 79, 253);
lineTo(79, 259);
lineTo(85, 265);
moveTo(103, 293);
curveTo(113, 319, 123, 335);
moveTo(76, 249);
curveTo(76, 259, 70, 263);
curveTo(84, 271, 90, 283);
moveTo(106, 318);
lineTo(112, 336);
moveTo(69, 263);
curveTo(29, 284, 29, 295);
curveTo(18, 331, 16, 372);
curveTo(33, 377, 55, 374);
curveTo(56, 369, 68, 369);
curveTo(73, 375, 65, 377);
moveTo(47, 292);
curveTo(56, 312, 69, 329);
curveTo(63, 334, 63, 340);
moveTo(57, 312);
curveTo(60, 339, 69, 356);
lineTo(67, 358);
moveTo(65, 353);
lineTo(69, 370);
lineStyle(1, 0x000000, 100);
moveTo(18, 363);
curveTo(40, 367, 48, 365);
curveTo(55, 359, 66, 360);
moveTo(19, 374);
curveTo(18, 387, 20, 400);
moveTo(64, 370);
curveTo(65, 388, 67, 400);
moveTo(83, 255);
curveTo(83, 260, 80, 261);
moveTo(137, 248);
curveTo(137, 259, 139, 269);
moveTo(138, 263);
curveTo(142, 267, 148, 268);
lineStyle(2, 0x000000, 100);
moveTo(138, 254);
curveTo(156, 263, 157, 310);
curveTo(161, 327, 162, 335);
moveTo(141, 258);
curveTo(156, 270, 173, 273);
moveTo(159, 269);
curveTo(168, 289, 166, 314);
curveTo(167, 328, 169, 336);
moveTo(193, 287);
lineTo(202, 298);
curveTo(208, 336, 222, 365);
lineTo(215, 373);
lineTo(213, 374);
lineTo(195, 371);
moveTo(186, 307);
curveTo(181, 333, 185, 337);
lineTo(186, 342);
moveTo(63, 344);
curveTo(72, 338, 84, 337);
curveTo(103, 338, 140, 335);
curveTo(170, 335, 190, 347);
lineTo(187, 353);
moveTo(183, 346);
curveTo(205, 368, 185, 396);
lineStyle(1, 0x000000, 100);
moveTo(213, 373);
lineTo(213, 400);
moveTo(136, 329);
curveTo(136, 331, 139, 335);
lineStyle(2, 0x000000, 20);
moveTo(131, 324);
curveTo(132, 325, 136, 329);
moveTo(139, 324);
curveTo(138, 325, 136, 329);
lineStyle(4, 0x000000, 10);
moveTo(131, 284);
curveTo(141, 280, 151, 282);
moveTo(119, 284);
curveTo(109, 280, 100, 284);
moveTo(123, 280);
curveTo(126, 282, 128, 279);
lineStyle(7, 0x000000, 10);
moveTo(79, 343);
curveTo(90, 339, 101, 341);
lineTo(155, 341);
curveTo(167, 339, 184, 349);
moveTo(72, 396);
curveTo(128, 389, 180, 397);
lineStyle(2, 0x000000, 20);
moveTo(132, 93);
curveTo(144, 95, 152, 105);
}

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注