as3教程 flash ActionScrip 3
2023年6月23日发(作者:)
ActionScript3教程系列【黑羽】ActionScript3.0系列教程(1):与Flash9先来一次亲密接触!如蒙转载,请留下我的Blog链接:,thx)FlashProfessional9ActionScript3.0Preview版本今天发布了,意味着从此我们从此不仅仅只能使用Flex2来使用AS3.0,更可以使用我们一直很熟悉的FlashIDE来进行AS3.0开发了。与Flex2不同,Flash9alpha(即上面的FlashProfessional9ActionScript3.0Preview)允许我们创建基于时间轴的ActionScript3.0的Fla文档,而不是基于State的MXML文档。在Flash9alpha里,我们和以前一样可以在舞台上直接手绘矢量图,创建元件,添加动画,等等。我黑羽是急性子,先跳开一些特色的介绍,单刀直入,马上来个实例。边讲解边说说Flash9的特点。点击看大图,清楚点。为了照顾新手xdjm们,看图说话一把。老鸟略过勿看,省得嫌我罗嗦。呵呵。新建一个fla,随便画一个方块什么的,双击选中按F8转换成MovieClip。在属性面板中命名为kingda_mc。和以前一模一样。再新建一层,命名为actions,这是个好习惯,要保持。选中第一帧,按F9打开动作面板,写入如下代码。Control+Enter,在测试窗口中,双击那个方块,就会有trace信息显示出来。//【黑羽】ActionScript3.0系列教程(1)//gda_ClickEnabled=true;kingda_ntListener(_CLICK,clickHandler);functionclickHandler(event:MouseEvent):void{trace("哈哈,你双击我了");}//直接支持双击了,兄弟们,爽不爽^_^稍作解释,这儿有几个和AS2.0不同的地方了。2.0中,MovieClip是不可以加侦听器地,但AS3.0中,却可以了。讲点深入的东东给老鸟听,所有AS3.0中能被我们看见的对象,其祖宗都是DisplayObject类。标准说法是都间接或直接的继承于DisplayObject类。而这个DisplayObject又是EventDispatcher的儿子。所以,我们就有了这个推论:AS3.0中所有能被我们看到的东西,都能发送事件和加侦听器。完全适用于EventModel.爽吧,我是爽歪了。AS2.0中为了解决这个麻烦我还自己编了一个代理发送事件类EventSender。省了不少事儿,而现在连这个也不用了,霍哈哈。3.0中要让MovieClip在接受click事件,rollover事件能够像Button一样,鼠标放上去显示手型,那么一定要加上一句:kingda_Mode=true;小事一桩,一笔带过。3.0中的事件模型和AS2.0大不一样了。简而言之,就是“规范”。不再直接使用字符串来定义事件名称了。又要讲深一点了,都是使用了新的const型变量来定义事件字符串名称,一旦定义,不能再更改。如publicstaticconstMOVE:String="move";极大的避免了我们因为手误,打错字符串,而花上一个下午找bug。使用了这种模式,我们一旦打错,编译器立刻会发现并告诉我们。多好。给出一些鼠标事件列表,大家可以替换上面源码中的事件类型,自己试着玩儿。如,你可以换成_OVER就变成了以前的onRollOver效果。CLICK:String="click"[static]Dispatchedwhenauserpressesandreleasesthemainbuttonoftheuser'ventDOUBLE_CLICK:String="doubleClick"[static]DispatchedwhenauserpressesandreleasesthemainbuttonofapointingdevicetwiceinrapidsuccessionoverthesameInteractiveObjectwhenthatobject'ventMOUSE_DOWN:String="mouseDown"[static]DispatchedwhenauserpressesthepointingdeventMOUSE_LEAVE:String="mouseLeave"[static]DispatchedbytheSOUSE_MOVE:String="mouseMove"[static]DispatchedventMOUSE_OUT:String="mouseOut"[static]DispatchedwheventMOUSE_OVER:String="mouseOver"[static]DispatchedwhentheusermovesapoinventMOUSE_UP:String="mouseUp"[static]DispatchedwhenauserreleasesthepointingdeventMOUSE_WHEEL:String="mouseWheel"//支持鼠标滚轮喽,霍霍。指出一点,在我给出的例子中,使用了双击这个事件。这个有点特殊,在使用双击事件之前,要加上一句:kingda_ClickEnabled=true;因为MovieClip对于双击事件默认是false,关闭的。4.侦听器的不同。在AS2.0中我们通常要新建一个对象做侦听器。也可以像我的例子中用function做侦听器。但是,很可惜,由于AS2.0的设计缺陷,使得function中的this指向常常给我们带来困扰。于是有了Delegate类来解决。而如今,AS3.0中采用了优秀的TraitsObject架构(唔,这个,就暂不解释了),使得它能记住this的指向。所以,兄弟们,放心大胆使用Function作为侦听器使用吧。今天就写这么多了,主要是Flash9出来,我老人家激动了一下,一下子写了这么多东东。希望对大家有所帮助,希望大家狂顶支持一把,不然没动力,本系列教程会变成太监贴!霍哈哈!^_^快回帖支持!本篇主要涉及了一下AS3.0中的事件模型部分,这是很重要的。以后会有更深入的教程来详细介绍。本篇的目的就是让大家使用一下Flash9和AS3,消除陌生感。写的浅了,还请包涵。下一篇介绍非常实用的东东,类和MovieClip的绑定,和Flash9中一大特色:DocumentClass。用来替代在时间轴写代码的好东东。【黑羽】AS3.0教程(2):AS3.0的类及绑定hi,鸟笼山的朋友们,这次我们开始介绍AS3.0中的类如何和库中元件绑定,和特殊的DocumentClass设计。总共4步:1.建一个标准的AS3.0类(暂命名为KingdaMC,多么伟大的名字啊,简称“有名”)2.新建一个元件,并设置它的Linkage和上面的类绑定。3.在时间轴上写代码,用AS3.0代码创建n份“有名”。4.删掉时间轴上代码,使用Flash9新特色DocumentClass在舞台上创造n份“有名”。just体验一把。(写起来才知道要讲的内容多啊,晕,打了两个小时,累了,本节专门只讲讲AS3.0的类吧,其余的慢慢再讲)在创建AS3.0之前,请允许我先对AS3.0类的语法和继承设计表示敬意。与标准的完全兼容,更好更严格的封装特性,特别是命名空间(namespace)的引入。从今天起从AS3.0起,在OOP层面上,AS3.0已经和Java,C#平起平坐了,甚至在某些方面(比如namespace)比java更有意思。让俺对AS2.0老鸟说几句憋在心里的激动之语:如果说AS2.0只是外表接近OOP标准语言,内在还是乱糟糟的AS1.0脚本语言,那么AS3.0不论是从OOP设计级别,还是从编译器级别(如,对弱引用——weekreference——的支持)来评估的都是标准、正宗、强大的语言。从AS3.0起,我们ActionScript开发者可以挺起胸口,俺们是真正的行业标准级程序员。在我继续教程之前,我要唱首歌给大家听:AS3的英明,绝对不是一句两句能说清!~~~~~~打完,收工。1.建立AS3.0类文件,类文件是干嘛用的?比如说,我们想让一个对象(Object)有很多功能,比如说这个对象是MovieClip型的,支持拖拽,支持双击等等。那么先在一个类文件里写清楚这些要求和实现方法,然后就可以用这个类创建许多实例,这些实例就全具有了这些功能。写一次,就能用很多次,多好。最重要的是它还可以通过继承来重用很多代码,为将来节省更多的时间。废话少说,Ctrl+N打开“新建”窗口,选择建立“ActionScriptfile”,Ctrl+S,暂存为""文件。(即“有名”的类文件)。输入如下代码://【黑羽】ActionScript3.0系列教程(2)////代码如下//package见讲解1package{lip;vent;//讲解2//讲解3publicclassKingdaMCextendsMovieClip{publicfunctionKingdaMC(){trace("Kingdacreated:"+);Mode=true;ntListener(,clickHandler);ntListener(_DOWN,mouseDownListener);ntListener(_UP,mouseUpListener);}privatefunctionclickHandler(event:MouseEvent):void{trace("Youclickedtheball");}functionmouseDownListener(event:MouseEvent):void{rag();}functionmouseUpListener(event:MouseEvent):void{ag();}}}讲解1:AS2.0中我们使用的是全饰名称来声明类,通俗说,包括了类的路径在类名前。AS3.0则把路径提取出放在package这个关键字后面。本文例子中的类文件和Fla文件在同一个目录下,因此package后面没有什么东西。如果类文件在org目录下的kingda目录里,那么就要写成//MC{}//{publicclassKingdaMC{}}你在package中可以定义好几个类,不用再写全饰名称了。但我不推荐这样做。一个文件一个类比较好管理。讲解2:MovieClip类再也不像AS2.0那样是默认的全局类了。你要使用MovieClip类一定要写这一句导入。讲解3:类在AS3.0中也有public和internal的区分了。public表示这个类可以在任何地方导入使用。internal表示这个类只能在同一个package里面使用。不写,就默认为internal这个新的关键字。还有一个属性是final,表示这个类不能被继承了,继承树到此为止。说白了,这三个属性都是用来让我们更加规范的管理类之间的关系,以便将来修改时心里有谱,大大的方便了修改。同时,对架构的设计能力要求更高,新手们和小项目还是多使用public吧。越到后来你会越喜欢internal的。我只要看到internal和private这两个关键字,心中就无比的稳定和舒服。想来不少programmer和我都会有同感吧。2.新建一个元件,并设置它的Linkage和上面的类绑定。和教程第一章一样,画一个方块,按F8转成MovieClip,再在库中右键点击它,选择"linkage"点击看大图。在Class里面写上KingdaMC。注意,id输入框已经被废止了。因为在AS3.0中,再也没有Movie(),EmptyMovieClip(),以及TextField()的存在了。所有舞台的可见对象都由new来创建。比如说本例中,symbol1绑定了KingdaMC,那么如果我要在舞台上创建一个KingdaMC,只要写varb1:KingdaMC=newKingdaMC();addChild(b1);即可。还记得以前那些乱七八糟的创建影片和组件的语法吗?什么createClassObject(),DepthManager的createChildAtDepth(),createClassChildAtDepth(),等等等等。我的一个java同事刚刚学习AS时,被上面哪些乱乱的创建函数弄得一头雾水。统统没有了。只有一统天下的newClassName(),多标准哪,多舒服啊,多好学啊。所以说,没学AS2.0直接学AS3.0绝对是新手的福气。第二句,addChild这个很重要。光有第一句new可不行。那只是告诉Flash我建了一个名字叫b1的KingdaMC要显示,但还没告诉Flash什么时候显示呢。你什么时候打addChild(b1),那Flash才会把它显示在舞台上。怎么样,多简单。其实这里省略了一个this。如果你有一个MovieClip名叫BigKingda,希望在这个BigKingda里面加上一个KingdaMC实例,那么就要写ld(b1);非常简单。Ctrl+Enter测试,发现创建的KingdaMC,支持拖拽。大家试着用代码多创建几个KingdaMC,比如用for循环来建个10个8个的来玩玩。好了,累了,要歇歇了,下次讲DocumentClass。本节代码例子参考了JendeHaan的教程,原因很简单,她选的例子很好的说明了绑定和DocumentClass,黑羽做了少量的中文改动。她原来的源码例子点此下载。AS3.0教程(3):DocumentClass特色为我们带来了什么?DocumentClass,中文直译为“文档类”。顾名思义,就是和文档绑在一起的类。文档是啥?就是要和这个类绑在一起的Fla文件。什么用处?这个玩意儿根本目的就是想把AS代码和Flash设计完全剥离。从此,Fla里面只管设计,逻辑代码全部由外部的类来包办。对于设计者和新手,黑羽可以打个比方,就好比三步走:1.把Fla里面所有代码集中到第一帧,2.再把第一帧里的代码拷贝到外部的一个as文件里。3.再按照AS3.0的形式,把这些代码放到这个类的构造函数里去。再根据这些个代码抽出一些类的属性和方法就OK了。唔,这个比喻有很多小毛病。但比较直观,比较好理解,一步步来。等你明白有哪些小毛病了,你已经不需要这个破比喻了。对于程序开发者(比如c#)DocumentClass就好比一个Entry,它的构造函数就相当于一个main函数。教程相关例子下载:点击下载先来一个例子:上次建立的和还在吧?删了?重来一遍吧,本次要用到fla里面的加好链接类的元件,以及相关的KingdaMC类文件。我们干两件事:1.新建一个DocumentClass类。2.用上之前的那个,绑定DocumentClass1.新建一个as文件,命名为KingdaMCDocumentClass,记得要和fla在同一目录下:输入如下代码://因为在统一目录下,所以package后面没有路径package{lip;publicclassKingdaMCDocumentClassextendsMovieClip{privatevartempMC:KingdaMC;//临时变量,持有当时创建的KingdaMC的引用。privatevarMAX_MCS:int=10;//最多创建的KingdaMC数目//构造函数,和类同名,在AS3.0中必须为public。不能用private,protected或者自定义的namespacepublicfunctionKingdaMCDocumentClass(){vari:int;//新的数据类型int,只要是整数,就请用int。效率快过Number。for(i=0;i主时间轴代码执行>舞台元件绑定的类初始化>元件的时间轴代码初始化>..下面的层次按这样的规律循环。Ok了,三大特色到此详细介绍完了。尽量讲的浅俗易懂,大家明白就好。而且黑羽也加上了一些高级讯息供老鸟参考。喜欢的顶一把!^_^下次开始AS3.0的本质之旅:AS3.0的新数据类型及本质P.S:本教程受CreativeCommonsLicense.协议保护,未经作者同意,不得用于商业用途。AS3.0教程(4):爽快使用XML为什么放弃AS2.0选择AS3.0?如果只允许我说三个理由。那么AS3.0对XML的近乎完美的支持绝对是其中一个。简单说说AS3.0中对于XML支持的不同吧:2.0对XML的支持勉勉强强,将就着可以用。而AS3.0中对XML的支持是全方位的,极其强大和灵活的。2.0对XML的支持不是内建的(build-in),也并非基于ECMAScriptforXML(E4X)标准。而AS3.0中对XML的支持符合E4X标准,它的设计有三个优点:1.简易。包括操作和可读性。你会发现AS3.0中对于XML的操作犹如对一个普通Object对象一样浅显易懂。语句非常浅白流畅。2.连续性。其各个功能的设计和AS3.0其余的部分思想一致,易于理解。3.熟悉。操作符和操作逻辑对我们来说都相当熟悉易用。在AS2.0时代,为了解决这部分的问题C.效率。效率包括两方面,开发效率,和代码执行效率。开发效率的论述见上。AS3.0对于XML的执行效率远远高过没有内建XML支持的AS2.0。XML的输入在AS2.0时代,在代码行中输入XML代码是一种痛苦。如果不是从文件中读取,那么我们就要忍受一长串挤在一块儿的字符串。而在AS3.0中,太简单了。直接按照XML的内容输即可,想换行就换行,想Tab就Tab,就一个字,爽。新建一个fla,选中第一帧,F9打开动作面板,输入如下代码://【黑羽】ActionScript3.0系列教程(4)////例1varkingdaXML:XML=2FirsttouchofFlash93BindingClasses4DocumentClasstrace([1].level);//例2varkS:String="thisisatest";varkXML:XML=newXML(kS);trace();//output:thisisatest;//output:3例1中注意到没,直接写XML内容在后面,想换行就换行,想tab就tab,多爽。不想AS2.0中写string时,换个行就不行了。写完这一句后,我们所写出的类似于string的形式立刻就被Flash理解成了XML对象了,所以我们马上就可以用"."操作符来访问相应的属性。本例中访问了第2个item节点的level值。这么简便直观的访问方式是不是比AS2.0中那千遍一律的childNodes要好得多?不过要注意,最后可以加";"结束。但我为了XML的视觉美观没有加。这个没有关系,编译时不会考虑这一点。事实上只要你喜欢,AS1.0,2.0,3.0中语句结束都可以不加";"号。但是这并不是一个好的编程习惯,更不符合严谨的自我语法要求。因此我建议,除了XML可以不加外,其余的都应该加,呵呵。例2展示了如何将一个包含了XML内容的字符串转换成XML对象。用的是XML的构造函数转换的。AS3更有趣的是,可以使用已有的变量来直接构造XML,带来方便的编程特性。如下例。varrootNodeName:String="site";varsubNodeName:String="orgin";varsubNodeContent:String="Kingda'sBlog";varattributeName:String="url"varattributeValue:String="";varextXML:XML=<{rootNodeName}{attributeName}={attributeValue}><{subNodeName}>{subNodeContent}{subNodeName}>{rootNodeName}>;trace(ng());/*output:Kingda'sBlog*/要点就是要把变量用"{}"括起来,并且设置属性时不要再加引号了。这个特性黑羽非常喜欢。XML的外部读取包括读取外部xml文件,和通过URL读取xml。AS3.0中不像2.0那样集成了一个load()。AS3.0在架构上就设计了所有与外部打交道的都由URLrequest对象来进行,数据都由URLloader对象来接受。这个我们会在下一部分教程详细讲解。这一次只要知道这样的架构设计是深思熟虑,且简洁优美的即可。varmyXML:XML=newXML();//初始化XML地址,可以是本地的"",也可以是如下的URL地址。varXML_URL:String="/blog/";//我的BlogRSSFeedvarmyXMLURL:URLRequest=newURLRequest(XML_URL);varmyLoader:URLLoader=newURLLoader(myXMLURL);//添加装载完成侦听器,//TE的值是"complete",直接用此字符串也可以。ntListener(TE,xmlLoaded);functionxmlLoaded(evtObj:Event){myXML=XML();trace("数据装载完成.");trace(myXML);}XML的操作。精彩的部分到了。详细看我下面的例子代码。1.查询//显示level为4的节点的title值trace(.(level==4).title);//output:DocumentClass//显示level>2的节点的title值,本处结果大于1,所以是一个XMLArray。trace(.(level>2).title);/*output:BindingClassesDocumentClass*///使用属性用@开头即可。真方便。trace(.(level>2).@id);//output:23//这儿要注意,实际上是2,3。一个Array.//也可以用属性来做判断trace(.(@id>1).title);2.添加或者修改属性方便的不能再方便,直接写即可。爽翻天啊。//把id==1的节点level值改为.(@id==1).level=2;//把id==1的节点添加一个属性.(@id==1).page=100;trace(.(@id==1));3.按某条件插入节点varnewNode1:XML=0NonevarnewNode2:XML=0None//把newNode1插入到id==2的节点后面kingdaXML=ChildAfter(.(@id==2),newNode1);//把newNode1插入到id==2的节点前面kingdaXML=ChildBefore(.(@id==2),newNode2);trace(kingdaXML);XML的高级操作。常用的操作上面已经介绍的很清楚了。高级操作则是留给对XML应用更深的兄弟们。几点注意:1.在AS3.0中,XML类的ignoreWhitespace默认为true。3.0支持对comments的直接操作。但默认Comments=false;varkingdaXML:XML= ;trace(tring());//默认为true时,不会显示comment的访问comment用trace(ts()[1].toXMLString());支持克隆。使用copy()可以得到一份现有XML的值拷贝。varkingdaCopy:XML=();对kingdaCopy操作就不会影响kingdaXML对象了。4.极有用的descendants函数返回一个XMLList对象,包括所有的子节点。设ignoreComments=false;和ignoreProcessingInstructions=false后,连comments和processinstructions也会包含在这个XMLList对象中。运用示例如下:Comments=false;varxml:XML=text1text2;trace(dants("*").length());//5trace(dants("*")[0]);////trace(dants("*")[1].toXMLString());//text1trace(dants("a").toXMLString());//text2trace(dants("b").toXMLString());//text2还有太多的XML有用操作功能了(如对namespace的操作)。用到时再去翻参考书吧。以上的介绍可以满足绝大部分运用了。打完收工,歇歇。对了AS2.0已有的XML类,在3.0中变成了XMLDocument类,使用方法不变。便于AS2.0程序移植。其余不推荐。下一次讲3.0的Web交互模型和运用吧AS3.0教程(5):强大的事件机制(上)(如蒙转载,请留下我的Blog链接:,thx)Event机制作为重头戏,在ActionScript3.0中加强了很多。更加统一、易用、标准、灵活。ActionScript2.0中有众多的事件实现机制:回顾和比较AS1.0玩家最爱用onClipEvent(),on(),又方便又直接。缺点在于逻辑分散到了各个舞台元件中,难以管理和维护。更加别说代码重用了。别跟俺说可以Copy,Paste,这不叫重用,这叫低级。AS2.0中,增加了一些事件处理机制:1.回调函数:onLoad,onComplete等。相信兄弟们最熟悉的应该就是回调函数了。2.事件侦听器型:这个就是addListener(),addEventListener()这种类型的。发送事件有的是内置,有的通过dispatchEvent().嗯,这种事件机制基本上就和AS3.0很像了。自从使用了ActionScript2.0来开发项目,黑羽就尽可能的多用这种事件处理机制。这个习惯很好,基本上让黑羽对3.0的机制很快适应过来。说道这里,黑羽要多扯几句2.0,抱怨一下它的不足,再让大家看看AS3.0的光明大道。(1).2.0中除了UIComponent能自己发送事件,绝大部分类不能自己发送事件的,比如MovieClip,或者一些自定义的类。黑羽还制作了一个EventSender的事件发送类来解决。当然你可以通过扩展来解决MovieClip这些类来解决,但是在一些轻量级或者特殊运用中,还是用黑羽这个EventSender类更加方便。比如说,你突然需要舞台上某个A_mc的运行到第20帧时发送一个"finished"事件出来,并且希望另外某个B_mc能够捕捉到这个事件,那么用一般的扩展方法不知道有多么麻烦!(1.要重做一个带有事件发送功能的类和A_mc通过某种方式绑定。2.同时确保在B_mc中要能访问到发送事件的对象并addEventListenr)。而用俺的EventSender类非常简单,A_mc中写("finished",this),B_mc中写tener("finished",listenerFunc),并可以通过属性直接定位A_mc,真是简单的不能再简单了。(请尽量以正规方法为主,不推荐频繁使用,不是好的编程习惯)(2)2.0中,侦听器的记忆是"有毛病"的。如果是新手,会经常觉得侦听器函数的this关键字指向飘忽不定,常常弄错。而且看看高手的代码,一会儿是Object做侦听器,一会儿是function做侦听器,真是让人头痛。其实MacroMedia也很头痛,所以就出了Delegate这个官方类(补丁?)来解决这些问题。(3)侦听器注册方式也有两种,一种是addListener(),如Key,一种是addEventListener(),如UIComponent类。为什么要这样搞两种?MacroMedia无辜的望着我,喃喃道偶也不完全清楚。超人来了,那就是ActionScript3.0事件处理机制:(1)统一。全部一色用addEventListener().(2)所有的可视对象都可以接受和发送事件。AS3.0的类继承设计是深思熟虑的,所有的可视对象所属类都是DisplayObject的子类,DisplayObject又是EventDispatcher的子类。因此它们就都可以玩Event了,所以说,有个好的老子就是好啊。而且有了崭新的事件冒泡机制,可以使事件层层上递到最上层的Stage,绝好的功能!有了以上两点:黑羽的EventSender类也可以歇菜了。(3)侦听器统一使用Function,不再使用Object了。同时this关键字的记忆力“大大增强”,Delegate类也可以下岗了。Event涉及到的内容极多,面很广。下面黑羽将从以下几个方面讲起:一、如何接收事件?如何做到AS3.0的标准事件编程。二、如何发送自定义事件?如何在OOP中正确使用AS3.0强大灵活的事件架构。三种方式及其优劣,以及在何种情况下使用。(1)用继承EventDispatcher实现(2)用复合EventDispatcher实例来实现。(3)用接口IEventDispatcher实现三、如何使用冒泡机制(即官方所称的EventFlow机制)?以及冒泡机制的原理。四、Event的其他高级应用。P.S:本教程受CreativeCommonsLicense.协议保护,未经作者同意,不得用于商业用途。【黑羽】AS3.0教程(6):强大的事件机制(2)(如蒙转载,请留下我的Blog链接:,thx)今天Google小查了一下,居然有1060个网站转载了俺的系列教程。还包括了Blueidea,flash8,5dmedia等顶级Web设计大站。非常开心,动力十足,呵呵。其实到目前为止,我的3.0开发学习笔记已经有3万字左右的东西了,但都是些纲要和代码,整理成文,尤其是用比较有条理和易懂的方式写出来会比较慢。况且开发中的代码是随手拈来,但写教程的代码往往要经过一些改写,使得重点更突出。所以如果更新有点慢,请耐心一些,呵呵。如何接收事件?如何做到AS3.0的标准事件编程?Event改变的部分很多,这两天有空时,黑羽就在想怎样用一个有条理的方式来讲解Event和它相关的诸多内容,让我们感到比较容易理解,记忆和接受。我准备这样来讲解:先给个接受事件的代码例子。在例子中,指出:(1)Event对象发生了什么变化(2)addEventListener语法的不同,原因,和const型必要性和用法(3)Listener和As2.0有何不同,和this关键字的“改进了的记忆力”黑羽一贯的风格,先来一个例子。我很想给个短一点的代码例子,但是要达到清楚,全面和标准的示范,我还是决定采用这个DocumentClass的示例。我会在每个代码段注一些注释,大家不明白的地方回贴说一下,我会尽量解答。DocumentClass的含义和相关用法并不难,忘了的兄弟看我第3篇教程:AS3.0教程(3):DocumentClass特色为我们带来了什么?好,comeonbaby.新建一个as文件,拷贝以下代码,命名为。新建一个fla,命名为"黑羽黑羽我爱你.fla"(本教程推荐使用,倘若不遵从可能导致喝凉水塞牙泡MM被踢炒股被套等严重后果,霍哈哈。Justkidding。)。设置它的文档类(DocumentClass)为AddListener.//【黑羽】ActionScript3.0系列教程(6)//kage{;vent;//哈哈,看到了没,DocumentClass不仅可以扩展MovieClip,也可以扩展Sprite//package里面的类名要和文件名相同publicclassAddListenerextendsSprite{publicfunctionAddListener(){//用package外面定义的类KingdaSprite创建一个实例,由于同文件中,所以不用import啦varoutsideChild:KingdaSprite=newKingdaSprite(0x00FF00,"outside_sprite");addChild(outsideChild);//没有了这一句,你啥都看不到。ntListener(,inclassHandler);//注册类里面的侦听器ntListener(,outsideHandler);//注册类外面的侦听器}privatefunctioninclassHandler(event:MouseEvent):void{trace("类里面的侦听器侦听到MouseEvent事件:"+event);trace("this关键字指向:"+this);}}}functionoutsideHandler(event:MouseEvent):void{trace("类外面的侦听器侦听到MouseEvent事件:"+event);trace("this关键字指向:"+this);};vent;//这个类就是画一个矩形,然后你点击这个矩形会发出标准鼠标click的事件classKingdaSpriteextendsSprite{publicvarnickname:String;publicvarColorNum:uint;//colorNumber就是#ffcc00这种类型的数,在AS3中推荐用新的uint型来标记它publicfunctionKingdaSprite(colorNumber:uint,nameString:String){ColorNum=colorNumber;nickname=nameString;ill(ColorNum);ct(0,0,100,100);l();}}鼠标一点击创建出来的绿色矩形,会看到输出类里面的侦听器侦听到MouseEvent事件:[MouseEventtype="click"bubbles=truecancelable=falseeventPhase=2localX=64localY=80stageX=64stageY=80relatedObject=nullctrlKey=falsealtKey=falseshiftKey=falsedelta=0]this关键字指向:[objectAddListener]类外面的侦听器侦听到MouseEvent事件:[MouseEventtype="click"bubbles=truecancelable=falseeventPhase=2localX=64localY=80stageX=64stageY=80relatedObject=nullctrlKey=falsealtKey=falseshiftKey=falsedelta=0]this关键字指向:[objectglobal]演示完毕,我们来讲第一个话题(1)Event对象发生了什么变化AS2.0中创建event对象是很随意的,只要这个对象有一个String属性叫做type的就可以了,甚至连target都可以省掉。不要以为这不规范不应该做,看看Flash类源码,Macromedia的程序员可不只一次的这样使用过。所谓上梁不正下梁歪,就是这样。(其实严格说也没什么不对,有时候是不需要target。但没有标准就是不好)然后你在EventObject中爱添加什么就添加什么。极其自由,也就等于极其混乱。3.0不同了,所有的事件必须都要继承自Event这个类(全饰名称)。不然,哼哼,事件发送是不能成功地。说说Event这个类,那叫一个NB。AS3.0的基石类是Object,Event是直接继承自Object的,开国大佬级别的。它里面定义了一些基本的事件名称,比如ACTIVATE(FlashPlayer得到系统焦点时事件),ADDED(对象被添加到显示时发送的事件)。AS3.0中有个好功能是cancel事件,但Event中这些基本事件统统是不能被cancel的,听起来似乎很NB。这不细说了,Event太多内容了。以后写高级内容时在提到如何运用吧。那叫一个爽字了的!要想Flash玩的转,Event类必须很精通。正所谓江湖人称:"平生不识Event,就称闪客也枉然。"这样有什么好处?好处太多了,最大的好处是一,规范了事件的定义,二,大量由此衍生的类省去了我们大量的时间和重复开发的成本。规范事件的定义放到下一部分讲。至于内置的Event子类好处,大家请看上面fla的运行输出:MouseEvent就是内建的一个Event子类,它的好处一看它的内容就明白:从AS3.0起,任何一次点击事件我们都可以得到:1.事件发生时鼠标的MC相对坐标(localX=64localY=80)和绝对坐标(stageX=64stageY=80)。爽不爽?键,shift键,alt键有没有按下。你试试按着ctrl键再点击一下方块,那么ctrlKey就为true了。爽不爽?(其余参数不解释,涉及到高级运用。部分会在Event最后一节提到该怎么运用)光这一个MouseEvent类,黑羽怎么着都觉得值人民币20块。(2)addEventListener语法的不同,和const型必要性这一节很重要,不过现在12点半了。精力不太好了,但又不想草草了事。明儿接着写,质量第一。数数也有小两千字了,先发出来顶顶先。【黑羽】AS3.0教程(7):强大的事件机制(3)(如蒙转载,请留下我的Blog链接:,thx)(2)addEventListener语法的不同,原因,和const型必要性和用法本例如果是AS2.0,那么代码是这样写的:ntListener("click",inclassHandler)本例是3.0,如果你trace一下其中的,输出的也是字符串"click"。看起来AddEventListener的方法和以前也没什么大的出入。和这世界上大多数相同的事物一下,表象的类似却掩盖着本质的巨大差异。我们先从最小的差异讲起:1.使用类静态属性,用const定义事件字符串名称变量AS3.0中用了一个新的关键字定义了事件名称字符串变量,代码是publicstaticconstCLICK:String="click"const,是英文constant的缩写,意思使不变的,常量。那就意思很明白了,一旦这种类型的常量被定义就不可再更改。好处通俗的说就是规范好项目,规范你自己,也规范任何其他项目人员,动不了这个变量。你可能还是会不屑一顾,这么小的一个改动,对我没什么用!可我的AS2.0开发血泪经验是,我曾经花了一个下午来找bug,最后却发现是某个类的addEventlistener()里面的事件名称"click"手误打成了"cilck"。编译器可不管这个。如果是3.0,你打成了,那么编译时立刻会报错提醒你,多好啊。一个项目一个人做十几个类还好办,自己认真点还能顶的住;如果是一个项目几个人几十个类,那么没有const和static的帮忙,管理事件类型还真是有点麻烦。即使实现了也没有AS3.0这么简单直观。回到代码,我们要记住,日后我们开发自己的Event类时,也要像这样,用publicstaticconst来定义我们自己的事件名称。如何自定义自己的事件,我会在EventDispatch那一节讲述。看看代码,我们还发现AS3.0中侦听器也发生变化了,只能用function来做侦听器,不再用Object。ntListener高级运用AS3.0中对侦听器的改进远远不止以上这些,看一看addEventListener的实现接口:functionaddEventListener(eventName:String,listener:Object,useCapture:Boolean=false,priority:Integer=0,useWeakReference:Boolean=false):Boolean;哇塞,有三个莫名奇妙的参数。可是当你知道这三个参数背后隐藏的巨大改进之后,相信你要大叫三个哇塞。第一个神秘参数,目前暂不解释,埋个伏笔,留到EventDispatcher那一节,讲ActionScript3崭新的EventFlow事件流机制.第二个参数:优先级。有趣吧,在ActionScript3.0中我们可以控制事件的优先级,从而达到控制function侦听器的执行顺序。如果你不填这个参数,那么事件默认为同一个级别0,事件的执行按先来后到的天经地义的顺序。如果设为1,那么事件级别降一个档次,稍后执行。数字越高优先级越高。级别可以为负数。(注意:FlexBuilder2Beta3中事件级别是越低越高)好好利用这个功能吧,在AS2.0中要想达到同样效果可不知道要多费多少力气!第三个参数,讲的是是否设为弱引用。兄弟们初学As2.0时一定经常忘了在删除Listener对象时,却忘了removeEventListener吧。这会导致很多莫名奇妙的情况发生。也是最常见的诡异bug种类之一。即使老鸟偶尔也会被阴一把。最郁闷的是这种情况往往不被发现,在后台默默的消耗大量资源。现在可以用弱引用可以在某种程度上解决这种bug。设为true,就是告诉垃圾回收器,这个侦听器function的引用是弱引用。一旦这个侦听器在运行时只剩下了这一个弱引用,那么垃圾回收器可以不理它,直接把它回收咯屁了,节省资源。从AS3.0引入这个弱引用这个概念就可以看出,AS3.0是如何的重视资源管理和有效率的运用。一个标准的重量级的程序语言必须具有这样的特征。现在AS3.0有了!下一节:(3)Listener和As2.0有何不同,和this关键字的“改进了的记忆力”【黑羽】AS3.0教程(8):强大的事件机制(4)本节内容:1.弱引用的使用原则er的不同和this关键字的指向。继续上次的话题。在讲listener和this关键字之前,我们先来讲讲一个高级话题:弱引用的使用原则。继续上次的话题。在讲listener和this关键字之前,我们先来讲讲一个高级话题:弱引用的使用原则。新手可以不看,因为暂时用不到。但这个话题很有必要。当设计大型RIA应用程序时,弱引用必须要了解。弱引用从原则上来讲,其引入是为了防止无意识的对象保留(unintentionalobjectretention)引起的内存泄漏。什么是无意识的对象保留?一般情况下,对象的逻辑生命周期和实际生命周期应当相同。但是在某些情况下,比如事件侦听器机制,我们可能会创建一个引用,它在内存中生存的时间比我们预期的要长很多。比如说,下面的例子中,即使删掉了侦听器lis,但事件还是能被继续捕捉。这是由于并没有removeEventListenr,那么系统中还会保留着对侦听器的引用。如果没有把addEventListener中对侦听器的持有改成弱引用,那么这个侦听器会一直存在、耗掉内存不被人发觉。但如果设成了弱引用,那么垃圾回收器过段时间后会将侦听器占用的内存回收,此时侦听器从物理意义上才真正的被销毁了。在销毁之前,这个侦听器还会继续存在,继续作用。这就是为什么下例中虽然已经把useWeakReference设为了true,但是还是会有作用。那么什么时侯垃圾回收器(GarbageCollector)才会来回收呢?唔,这要看它高兴了,快的话10分钟,慢的话一个月。哈哈,开玩笑,垃圾回收器的工作时间咋一看确实是不可测的,但也有规律可循。但这个问题探讨在本系列教程中显得过于艰深,黑羽会单独撰文来说明垃圾回收器的部分工作机制。那么推论来了,我们凭什么要把useWeakReference设为false呢?除非我们有意要让某个侦听器在失去了其他所有引用的时候还要工作,才有可能这样做。但谁会有这样疯狂的想法呢?道哥还是包世宏?所以,我建议,大家不妨养成习惯,把useWeakReference设为true。当然最好的做法是始终记得不用侦听器了,一定要removeEventListener。在这一点上,我们要坚持“始乱终弃”!!//这个是DocumentClass,建个fla,绑定这个class。忘了,就看我第三篇教程。package{lip;ispatcher;vent;publicclassLearnEventsextendsMovieClip{functionLearnEvents(){varlis:Function=function(){trace("听到了鼠标Click事件!");}varkingda_s:KingdaSprite=newKingdaSprite(0xFFCC00,"kingdaSquare");addChild(kingda_s);kingda_ntListener(,lis,false,0,true);//瞧,最后一个参数,已经把弱引用设为true了lis=null;//这一句,我已经从逻辑上删掉lis了,大家作证啊trace("侦听器还在吗?:"+lis);Click事件仍然被捕捉到。//lis也确实指向null了。但你只要继续点击方块,你会发现}}};vent;//这个类就是画一个矩形,classKingdaSpriteextendsSprite{publicvarnickname:String;publicvarColorNum:uint;//colorNumber就是#ffcc00这种类型的数,在AS3中推荐用新的uint型来标记它publicfunctionKingdaSprite(colorNumber:uint,nameString:String){ColorNum=colorNumber;nickname=nameString;ill(ColorNum);ct(0,0,100,100);l();}}Listener和As2.0有何不同,和this关键字的“改进了的记忆力”DOMLevel3中规定的是用Object来做listener。该Object有用来处理事件的方法(method)。AS3虽然是按照DOMLevel3事件机制设计的,但也不完全听话,有自己独立的想法。在AS3中,侦听器就是函数。也只能用函数来侦听。其实在ActionScript3中,Function实质也是一种特殊的Object,和AS2.0有相似之处。见我的文章:ActionScript高级技巧:深入了解Function因此AS3.0为什么限定用Function,这和它的架构有关,不细说了。但有趣的是,在AS3.0中,对IEventDispatcher的定义中,仍然按照DOM3标准用Object来做Listener。见黑羽上一篇教程和随后的评论。那么问题来了,function中this关键字的指向会怎样?AS2.0开发者对AS2.0事件机制中this关键字的水性杨花应该深有认识。如果用function做侦听器,那么谁发出事件,this就指向谁。这就等于对象之间乱搞关系,啊呀呀。所以MM派了一个Delegate代理警察类来管理。唉,糜乱的岁月不堪回首啊。//ActionScript2.0例子:拷贝以下代码到第一帧,拖一个button到舞台,命名为kingda_btn;functionlisFunc(){trace("亲爱的,你会指向谁:"+);}//我们本意应当是指向_root;kingda_ntListener("click",lisFunc);//点一下button,看看指向谁。回到ActionScript3.0,来看看坚定的夫妻关系,黑羽总结为:嫁鸡随鸡,嫁狗随狗,什么都不嫁,那就属于global。我靠,读一下,还挺押韵。大家也好记。简单的解释一下,函数在哪个对象里(应该叫method),那么this就指向谁。不在对象里,那么就指向global。//【黑羽】ActionScript3.0系列教程//kage{;vent;publicclassAddListenerextendsSprite{publicfunctionAddListener(){//用package外面定义的类KingdaSprite创建一个实例,由于同文件中,所以不用import啦varoutsideChild:KingdaSprite=newKingdaSprite(0x00FF00,"outside_sprite");addChild(outsideChild);//没有了这一句,你啥都看不到。ntListener(,inclassHandler);//注册类里面的侦听器ntListener(,outsideHandler);//注册类外面的侦听器}privatefunctioninclassHandler(event:MouseEvent):void{trace("类里面的侦听器侦听到MouseEvent事件:"+event);trace("this关键字指向:"+this);}}}functionoutsideHandler(event:MouseEvent):void{trace("类外面的侦听器侦听到MouseEvent事件:"+event);trace("this关键字指向:"+this);};vent;//这个类就是画一个矩形,然后你点击这个矩形会发出标准鼠标click的事件classKingdaSpriteextendsSprite{publicvarnickname:String;publicvarColorNum:uint;//colorNumber就是#ffcc00这种类型的数,在AS3中推荐用新的uint型来标记它publicfunctionKingdaSprite(colorNumber:uint,nameString:String){ColorNum=colorNumber;nickname=nameString;ill(ColorNum);ct(0,0,100,100);l();}}【黑羽】AS3.0教程(9):强大的事件机制(5)(如蒙转载,请留下我的Blog链接:,thx)有兄弟反映,似乎AS3的事件机制有些复杂。在我看来,编程上“复杂”这个词一般有两种定义:实现麻烦,或者内容众多。AS3中的事件机制其实现并不麻烦,逻辑更加清楚简单,因此不是“实现麻烦”这一类。那应该指的是“内容众多”这个意思。黑羽倒觉得"内容众多"往往是褒义词,意味着API丰富,控制范围和深度大。那么一旦得其要领,即思路通畅,记忆深刻,也就不会觉得“复杂”了。我也会尽量写的简单通俗,照顾新手。但我又要同时考虑到AS2老手们的需求,不让他们打瞌睡。所以AS初学者看到不懂的地方可以跳过,多用用Event后,有需要再回过头看看我教程的其它部分,一定会有收获。拿今天要讲的事件发送来说,我预计写以下内容:ispatcher和Event的简介2.回顾AS2.0事件发送3.继承EventDispatcher进行事件发送。4.合成EventDispatcher进行事件发送。5.实现IEventDispatcher接口来进行事件发送。与设计模式中的装饰器模式相似。那么新手看第一,第二,第三部分已经足够应付一般应用。AS2老手们要看看第四部分。开发大型项目的AS开发者,则第五部分必看。ispatcher和Event的简介。AS3中Object是万物之宗母,且生养众多,共有220多个子类。Event(事件类)和EventDispatcher(事件发送者类)就是在这一代之中。Event和EventDispatcher是事件机制的两大主角,二者缺一不可。Event类及其子类的功能就是提供各种具体的事件供EventDispatcher使用,不能干别的。EventDispatcher则是要让它所有的子类都能发送事件。那么,AS3就让所有要发送事件的类都统统继承于EventDispatcher。而需要发送事件的类毫无疑问,都是些很重要的类,比如URLLoader,DisplayObject。其中DisplayObject更是一代霸父,所有可视对象,比如MovieClip,Spirit等等等等统统都是它的子孙。因此,父以子贵,EventDispatcher在Object的第一代子女中,位高权重,影响极大。2.回顾AS2.0中发送事件AS2.0中发送事件是怎么干的?在类中留几个函数对象,如dispatchEvent:Function,再搞一个lize()来初始化一下要发送事件的类,然后,就搞定了。.....好简单。但AS3中更简单,更加标准。3.继承EventDispatcher进行事件发送。继承是最方便最快的一种。刚刚说过了,所有的可视对象都继承DisplayObject,是EventDispatcher的孙子辈,因此都可以直接使用dispatchEvent()来发送事件了。看代码,我们让一个普通的MovieClip,KingdaMC,来发送一个莫名其妙的事件,比如说"KingdaPlaySC"。chEvent(newEvent("KingdaPlaySC"));现在我们要让一个我们自己的类来发送事件。//【黑羽】ActionScript3.0系列教程////以下为一个名叫KingdaSampleClass的DocumentClass,请自行和一个Fla绑定。//如果忘了怎么弄,看我第三篇教程package{;;publicclassKingdaSampleClassextendsSprite{publicfunctionKingdaSampleClass(){//生成一个KingdaSampleDispatcher的实例vardispatcher:KingdaSampleDispatcher=newKingdaSampleDispatcher();//标准的实现ntListener(,actionHandler);thing();//可以用直接字符串标识事件类型,但推荐使用静态加const的字符串ntListener("KingdaPlaySC",anotherHandler);//直接用newEvent生成一个新的事件对象,该对象的事件类型为"KingdaPlaySC"chEvent(newEvent("KingdaPlaySC"));//输出://action的侦听器:[Eventtype="action"bubbles=falsecancelable=falseeventPhase=2]//KingdaPlaySC的侦听器:[Eventtype="KingdaPlaySC"bubbles=falsecancelable=falseeventPhase=2]}privatefunctionactionHandler(event:Event):void{trace("action的侦听器:"+event);}privatefunctionanotherHandler(event:Event):void{trace("KingdaPlaySC的侦听器:"+event);}}}ispatcher;;classKingdaSampleDispatcherextendsEventDispatcher{publicstaticvarACTION:String="action";//如果你需要在自己类中某个方法中发送事件,那么示例如下publicfunctiondoSomething():void{//你的代码.....//发送事件dispatchEvent(newEvent());}}【黑羽】AS3.0教程(10):强大的事件机制(6)(如蒙转载,请留下我的Blog链接:,thx)(2007-10-30update:呵呵,更正了一个手误。最后一个代码例子中的最尾部的花括号应该放在第一个class的结尾后。这样下面的kingdaClass才是包外类。否则编译不会通过。sorry^^谢谢daozi的细心。)事件机制写的太多了,我自己都有点烦了。但没办法,,太重要了。而且AS3做了这么多好的改进,值得我们去一一探寻,给我们日后的编程带来极大的便利。ActionScript初学者,本节可以跳过不看。ActionScript2熟练工应当看看,有些价值。今儿讲掉4.合成EventDispatcher进行事件发送。5.实现IEventDispatcher接口来进行事件发送。与设计模式中的装饰器模式相似。这样事件的发送和接受,就可以讲完了。那么,事件部分就这样完了?没有!你晕,我也同晕。因为还有一个很重要的特性,Eventflow机制还没讲。这就是我所说的事件冒泡机制。给我们编程带来了莫大的方便。好,下面先讲:4.合成EventDispatcher进行事件发送。什么情况下用合成EventDispatcher来发送Event呢?一般发生在某个较复杂的类里面。这个类可能是因为本身已经继承了其它类,无法再继承EventDispatcher。如果仅仅是因为这个原因,那么我更加建议使用实现IEventDispatcher接口来进行事件发送。但如果原因不止如此,比如,我们不愿意这个类不是一个单纯事件发送类,而是在执行某个方法(method),比如doSomething()时,附带的发送一些事件。这些事件发送者往往是这个类的组成部分,一些更小的类,通常是Sprite等。那么用这种做法就比较合理。看代码例子//【黑羽】ActionScript3.0系列教程////以下为一个名叫KingdaSampleClass的DocumentClass,请自行和一个Fla绑定。//如果忘了怎么弄,看我第三篇教程package{;;ispatcher;publicclassLearnCompositeEventsextendsSprite{publicfunctionLearnCompositeEvents(){varkingdaObj:KingdaClass=newKingdaClass();//一定要用der()来返回事件发送对象,才能der().addEventListener(,lisFunc);thing();//输出://doSomething//listened:yeahyeah}//侦听器privatefunctionlisFunc(evtObj:Event):void{trace("listened:"+);}}ispatcher;;classKingdaClassextendsEventDispatcher{publicvar_dispatcher:EventDispatcher;publicstaticconstACTION:String="yeahyeah";publicfunctionKingdaClass(){initSender();}privatefunctioninitSender():void{_dispatcher=newEventDispatcher();}//调用一个专门的方法(method)来返回发送事件的EventDispatcher。publicfunctiongetSender():EventDispatcher{return_dispatcher;}publicfunctiondoSomething():void{trace("doSomething");//除了以下两行发送事件,还可以写入其它你要干的事儿。灵活。varevtObj:Event=newEvent();_chEvent(evtObj);}}}5.实现IEventDispatcher接口来进行事件发送。在哪种情况下使用?类可能是因为本身已经继承了其它类,无法再继承EventDispatcher。而我们恰恰希望它能实现EventDispatcher类所有功能,比如说addEventListener,hasListener等等,看起来简直和继承EventDispatcher没什么分别。那么OK,我建议使用实现IEventDispatcher接口来进行事件发送。其实质是一个装饰器模式(Decorator),以对客户端透明的方式扩展对象功能,是继承关系的一个替代方案。其关键在于扩展是完全透明的,使用起来和继承父类几乎没什么区别。具体方法由于IEventDispatcher需要实现5个接口,addEventListener,hasListener,willTrigger,removeEventListener,hasEventListener,那么我们的装饰类也必须实现这五个接口。其余看代码优点:1.类的用户完全感觉不到差别2.在被包装的方法中还可以加入其它自己希望加进去的动作,比如,在addEventListenr方法中可以再插入一个计数,看看到底被add了多少次,超过某些次后,调用某个方法等等。总而言之,给我们带来了极大的灵活性。这就是装饰器模式的好处。package{;;vent;ispatcher;publicclassLearnDecoratorEventsextendsSprite{publicfunctionLearnDecoratorEvents(){varkingdaObj:KingdaClass=newKingdaClass();ntListener(,lisFunc);//用起来和EventDispatcher对象一样哦,呵呵。varevtObj:Event=newEvent();chEvent(evtObj);//确实一样吧:)//输出:listened:yeahyeah}privatefunctionlisFunc(evtObj:Event):void{trace("listened:"+);}}}Dispatcher;ispatcher;;classKingdaClassimplementsIEventDispatcher{publicvar_dispatcher:EventDispatcher;publicstaticconstACTION:String="yeahyeah";publicfunctionKingdaClass(){//initSender();}privatefunctioninitSender():void{_dispatcher=newEventDispatcher(this);}//哈哈,在实现接口时还可以乘机干点别的,比如我喜欢吧useWeakReference设为truepublicfunctionaddEventListener(type:String,listener:Function,useCapture:Boolean=false,priority:int=0,useWeakReference:Boolean=true):void{//dootherthings;_ntListener(type,listener,useCapture,priority,useWeakReference);}publicfunctiondispatchEvent(evt:Event):Boolean{//dootherthings;return_chEvent(evt);}publicfunctionhasEventListener(type:String):Boolean{//dootherthings;return_ntListener(type);}publicfunctionremoveEventListener(type:String,listener:Function,useCapture:Boolean=false):void{//dootherthings;_EventListener(type,listener,useCapture);}publicfunctionwillTrigger(type:String):Boolean{//dootherthings;return_igger(type);}}【黑羽】AS3.0教程(11):视觉元件精要(1).题外话:不少兄弟问我,AS3教程咋不出了哩?其实看我博客的兄弟们应该都知道,黑羽目前的FlashRIA整体网站,接近竣工,11月即将推出。结尾工作实在太多,从十一到上周末,基本上放假都在加班。一些博客或者论坛上兄弟的问题都没有精力回复,抱歉了。上次还在5d上看到版主鼓动大家给我打气,让我继续,真是非常不好意思。这个周末偶得空闲,遂集中精力,将自己开发笔记整理了一篇放上来。项目发布后,更新会正常。彻底了解AS3视觉元件架构DisplayObject,直译为视觉对象,意为可以被看到的对象。视觉是Flash成功的主要基石。当我赏析ActionScript3的所有视觉元件类型和其整体构架时,感到非常满意。可以看出,这次整体的架构设计是深思熟虑的结果。与其他语言,比如C#,相比有自己强烈的特色,是对Flash视觉行为贴身定做的结果。ActionScript3的架构乍一看很复杂,不包括UIComponent的子类,就有7到8个层,20多个莫名奇妙的类。头疼!但实际上,它的设计是非常的简洁优雅,远远比ActionScript2一个MovieClip打天下强太多了。实际上,只要真正弄清了它的设计思路,就可以高屋建瓴,一览无余,会发现这个架构逻辑清晰,非常的易懂易记。所以,先抛开ActionScript3的帮助文件,我们一起来看看为什么要设计这样一个架构,搞出20多个怪胎出来。(如蒙转载,请留下我的Blog链接:,thx)先来追忆一把ActionScript2中无所不能的先贤:MovieClip(影片剪辑)。这位兄台无所不能:可在其中画矢量图,可在其中贴位图;可在其中做影片,也可嵌套子影片;偶尔用来加载,闲来客串按钮;三教九流皆可放,肚皮天下第一广。它的父亲何人,原来是元始天尊Object。这样的玩意儿,新手用起来很爽,大大节约了脑细胞。但任何一个有过大型OOP项目经验的老手,都会毫不犹豫的指出,这样的架构设计是失败和混乱的。代价是巨大的。MovieClip类公开的属性和方法共有一百多个(自己数数)!居然直接继承根类!居然拥有这样多公开(public)属性和功能的类!居然应用范围如此广泛!首当其冲,其第一弱点就是系统资源的浪费。举个例子,我新建一个空MovieClipA,只是想让它做个容器,好在里面放几个有内容子MC。这样我操作A的位置和渐变时,子MC会统一变化。这样的经验大家都有吧。可就是这么一个简单的纯容器A,ActionScript2&1都会毫不犹豫的把MovieClip所有的属性和方法都赋给A。谁让A是MovieClip类的实例呢?可在这个应用上,我们要A的其他90多个功能干什么呢?而且还不算最耗资源的内建的对Timeline的支持!大家想想,我们每天都在创建MC。但事实上我们做开发时,创建的MC有多少用到了大部分的功能和Timeline?只有一部分的通过Flash创建的MovieClip才需要时间轴的支持,其余大部分根本不需要时间轴支持。这样的设计是不是有问题呢?痛批了一顿ActionScript3之前的MC后,我们不得不说几句公道话:这样的错误是有其历史局限性的,我们不能苛求古人。且看现在的视觉元件架构,那叫一个爽。爽,就爽在系统设计师对整个Flash视觉系统的抽象上。抽象和解构的功力很深!不得不佩服!系统各个超类和子类的设计划分,职责清晰,稳健高效,堪称优雅!我看.NetFrameWork的g架构设计时都没有这个感觉。毕竟Flash是靠视觉起家,与视觉动画交互打交道最深阿。下面来欣赏ActionScript3的元件架构。ActionScript3中所有可以被看到的视觉元件都统一于DisplayObject,即其子类的实例。DisplayObject是一个抽象类,不能生成实例。从系统架构设计上来说,这样的超类设计是常识。DisplayObject,我在AS3.0教程(5):强大的事件机制(1)中讲过,继承于EventDispatcher类,也就意味着所有的DisplayObject子类都可以发送事件了。啊哈,DisplayObject下面一层的抽象就精彩了,架构设计师的原意是将所有视觉元件分为两大类:可以接受人机交互事件的,和不可以接受人机交互事件的。所以就有了InteractiveObject类和非InteractiveObject类之分。由于非InteractiveObject的几个类之间差别太大,也抽象不出什么共同点,所以,干脆就分成了InteractiveObject的六个同级兄弟AVM1Movie,Bitmap,MorphShape,Shape,StaticText,Video。但黑羽认为从系统的优雅性出发,不妨就设一个UnInteractiveObject的超类,将这六个孩子放在这个超类的下面。还便于日后的功能扩展。在讲最重要的InteractiveObject之前,我们先把这几个不伦不类的兄弟先扫掉。这几个子类中,我们把它分为可以代码创建的,和不可以代码接触的。所谓不可以代码创建的,是指只能通过Flash创作工具来创建的。和以前一样,StaticText还是不可以用代码实现。另外一个是MorphShape,这个东东是指在Flash中创建Shape形变时,由FlashPlayer自动生成的,同样的,代码无法实现。剩下的几个都是可以用代码创建的:Bitmap,位图对象,可以通过BitmapData对象来创建,也可以从外部载入,比如通过loader。Shape,形状,专门用来绘制矢量图的,通过Graphic对象创建的。Video,视频对象,专门用来播放视频的,可以来自文件也可以来自网络流媒体。下面要说到的是AVM1Movie,所谓AVM1Movie,意思就是说ActionscriptVirtualMachine1所支持的SWF影片,也就是ActionScript1和2的影片。由于ActionScript3采用的是AVM2,所以和AVM1影片无法跨脚本交流,必须要把它同AVM2swf影片区分开来,所以有个这个类。关于这个,感兴趣的兄弟看我的这篇文:小谈ActionScript3.0与AS2.0,1.0的swf兼容性。这个一般我们不用关心,也不用直接接触,一旦我们加载一个AVM1老影片到AVM2swf中时,FlashPlayer会自动创建一个AVM1Movie的实例包装这个swf。我们打交道的往往是装载AVM1swf的容器元件。到了InteractiveObject下一层了,这一层共有三个类。这一层的抽象理念又要赞一下。架构设计师又用了一个容器和非容器的概念来区分视觉元件。所谓容器,就是可以在其中加载其他的DisplayObject子类对象。当然也包括它的叔叔们,即非InteractiveObject的那几个类。所谓非容器,那就是说不能在它的视图里面加入其他的DisplayObject了。“容器”,这个公共性质实在太重要了,在这一层才这样抽象出来实在很高明,很到位。那么老套路,先讲讲非容器的两个类,TextField和SimpleButton。TextField,就基本上是我们熟悉的动态文本框,这里暂不细说。来说说SimpleButton,这个名字虽然和我们在ActionScript2中碰到的SimpleButton一样,但实际上二者有很大的差别了。实质上,ActionScript3中
发布者:admin,转转请注明出处:http://www.yc00.com/news/1687518114a16412.html
评论列表(0条)