zoukankan      html  css  js  c++  java
  • ActionScript 3.0动画基础4

    本文作者:egoldy
    文章出处:http://www.webstudio.com.cn
    文章性质:翻译
    阅读次数:5953
    发布时间:2007-07-08
    声明: 此文章为未出版的keith peters的ActionScript 3.0 making things move中文版样章。为书中的第二章。webstudio会在中文版出版之际,友情提供论坛forum支持。转载请注明出处,谢谢!

    接上一篇.....



    2.6显示列表display list

    在AS3之前,你可以在一个Flash影片中创建不同数量类型的可视对象,包括影片剪辑,图形元件,按钮,文本域,位图,组件,和基本的图形。这些对象实际上并没有被组织成一定的层次结构,并且他们都有各自不同的创建,销毁,和操作的方法。举例来说,影片剪辑可以通过贴加(attach),复制,或通过动态创建放置在舞台上。文本域可以动态的创建或是在Flash IDE中创建。当你在创建位图,视频,组件和其它的内容时,他们看起来象是在不同的平台上创建的,然后被堆放在Flash中,并强行让他们在一直工作。
    在AS3中,这些不同的对象现在都被统一规化在一个地方。你所看到的舞台上的任何对象都由DisplayObject类的扩展所创建的。换种角度讲,所有的对象都是一个大家庭的一部分,他们都有着相同的基本行为,根据这点你可以知道怎样创建他们,把他们放在舞台上,销毁他们,并在舞台上操作他们。
    现在创建一个精灵(sprite),一个影片剪辑,或一个文本域的方法非常的相似。实际上,所有的显示(display)对象现在都使用相同的方法创建,这种方法也是你创建其它任何类型对象的方法,那就是使用new操作符。为了验证这一点,下面给出如何创建这几个对象:
    代码:

    var  myTextfield:TextField  =  new  TextField();
    var  myMovieClip:MovieClip  =  new  MovieClip();
    var  mySprite:Sprite  =  new  Sprite();


    这种方式是不是更简单呢?
    你已看过前面的范例了,如果你已经创建一个影片剪辑或是精灵(sprite),现在你可在那些对象里绘制内容,如下:
    代码:

    mySprite.graphics.beginFill(0xff0000);
    mySprite.graphics.drawCircle(0,  0,  
    40); mySprite.graphics.endFill();


    但是如果只是象上面那样做了,你可能看不到任何内容。这就是我们将要讨论的显示列表(display list)。“display list”术语是一个新增的,但是如果你使用Flash已经有一段时间了,它不应当是一个完全陌生的概念。把你影片中的所有可视对象想为一个树形。树的最底部是舞台,它默认状态就是可视的。在舞台上,你可能还有几个影片剪辑或其它类型的可视对象(文本域,图形等等)。当你将他们加入到舞台上时,他们也会变成可视的。在那些影片剪辑内部可能还会有其它的影片剪辑或其它的可视对象,并且在其它的内部也可能会有。这就是最基本的显示列表(display list)。

    显示列表(display list)工作方式是AS2与AS3中最大的不同之处。在AS2中,当你通过attach命令或是使用createEmptyMovieClip创建一个影片剪辑, 它必须要在创建时指明它将放在哪里。另外一点,影片剪辑被创建后,被放置在一个指定位置的列表中,那就是它所要留的地方。移除影片剪辑时,没有办法在位置列表中改变它的位置或是让它从列表中彻底销毁。
    在AS3中,当你创建一个新的影片剪辑,精灵,或其它的显示(display)对象时,它不会自动的加入到显示列表(display list)中。注意在刚刚给出的sprite范例中,当创建精灵(sprite)时没有提到过父级(parent)或是深度(depth)。它们是可以存在的但并不是在显示列表(display list)中被操作的。
    如果从字面意义上理解“stage”(舞台),你可以想象那些对象就是幕后的演员,收起翅膀,悬在舞台的上空,或是想象为趴在地底下。你不能看见他们,但是他们都在那里,繁忙的准备着他们的入场,到那时他们将跳上舞台并且真实的显示出来。
    现在为止,我们已经使用了树的比喻和一个剧院的比喻---还有其它的比喻吗?我们也可以将显示列表(display list)想象为一个大家庭,一个这样的parent/child/sibling家族关系。当你加入某些东西到显示列表(display list)中,对象将被加入到父级(parent)中,那么新加入对象就是父级的儿子。如此这样,当你增加一个对象到列表中时它是有理性的。你需要使用addChild方法来完成。
    你的文档类(document class)就象是一个树的根(或是所有可视对象的伟大的父亲,如果你愿意)。它是自动可视的,然后你开始为它加入孩子。因此,如你看到的之前的范例,要使精灵(sprite)或其它显示对象(display object)可视,传递给它一个新创建的精灵(sprite):
    代码:

    var  mySprite:Sprite  =  new  Sprite();
    mySprite.graphics.beginFill(0xff0000);
    mySprite.graphics.drawCircle(0,  0,  40);
    mySprite.graphics.endFill();
    addChild(mySprite);


    如果你试一试这些,将这些代码放在之前类结构中的init函数中。注意它将放置在原点0,0上。你可以通过调整x,y属性来改变它的位置。还要注意的是这里没有提到深度(depth),深度如同当我们在AS2中创建影片剪辑或使用attach贴加他们的过程。虽然深度管理大部分情况下是自动的,但仍有加入子对象的方法可以加入到指定的深度或改变它的深度,这些在我们需要的时候我们会讲到。
    要从一个显示列表(display list)中移除掉一个对象,调用removeChild方法,传递一个子对象的引用。第一个关键的地方是要意识到移除一个子对象并不是销毁它!它会保持与你移除它之前一样的状态而存在的。并且在将它加入回显示列表(display list)时仍保持原有的状态。换种角度讲,在AS2中,如果你已经在子对象中绘制了一些图形,或载入了些外部内容到子对象中,当你要将它加回到显示列表(display list)中时,将不得不重新绘制或重新载入那些内容。
    第二个关键的地方要意识到当你将一个子对象加回到列表中时,你可以自由的将它放在任何地方。这被称为重设父级(reparenting)并且是令人兴备的(至少对我是这样)。你可以从一个影片剪辑移除一个对象并将它贴加到另一个对象中,当你移除它时它会保持原有的状态,这在之前版本中是不可能的。实际上,你不需要移除它,因为一个子对象只能有一个父级,将它加入另一个父级会自动先从原来的父级移除。
    The following class demonstrates reparenting:
    下面的类演示重设父级
    代码:

    package  {
    import  flash.display.Sprite;
    import  flash.events.MouseEvent;

    public  class  Reparenting  extends  Sprite  {
    private  var  parent1:Sprite;
    private  var  parent2:Sprite;
    private  var  ball:Sprite;
    public  function  Reparenting()  {
    init();
    }
    private  function  init():void  {
    parent1  =  new  Sprite();
    addChild(parent1);
    parent1.graphics.lineStyle(1,  0);
    parent1.graphics.drawRect(-50,  -50,  
    100,  100); parent1.x  =  60;
    parent1.y  =  60;

    parent2  =  new  Sprite();
    addChild(parent2);
    parent2.graphics.lineStyle(1,  0);
    parent2.graphics.drawRect(-50,  -50,  100,  100);
    parent2.x  =  170;
    parent2.y  =  60;

    ball  =  new  Sprite();
    parent1.addChild(ball);
    ball.graphics.beginFill(0xff0000);
    ball.graphics.drawCircle(0,  0,  40);
    ball.graphics.endFill();
    ball.addEventListener(MouseEvent.CLICK,  onBallClick);
    }

    public  function  onBallClick(event:MouseEvent):void
    {
    parent2.addChild(ball);
    }
    }
    }



    这个类创建了三个精灵(sprite):parent1,parent2,和ball。Parent精灵直接加到显示列表(display list)中,并且方块被绘制在它们的内部。Ball精灵(sprite)被加入到parent1中,因此现在它存在于显示列表(display list)中并是可视的。
    当小球被点击时,它会加入到parent2中。注意这里没有改变它的x,y位置的代码。它会发生移动是因为它在位置不同的精灵(sprite)中。还有要注意的当精灵(sprite)在移除和加入的过程中,动态绘制的圆形会始终保持着。

    2.6.1子类中的显示对象(display object)

    在前面,你已经学习了在创建文档类(document class)时精灵(sprite)和影片剪辑的子类。这些类的子类还有许多的其它用途。
    首先,你可能在想,因为在AS3中attachMovieClip不在可用了,那如何在影片运行时将Flash CS3 IDE库中的影片剪辑元件放入到影片中呢?答案是使用一个扩展了精灵(sprite)或影片剪辑的子类。虽然我努力的在创建SWFs影片时不去使用任何的工具,但我们还是要回到Flash IDE中来解释它。
    通过下面的例子是最好的说明:
    1.  创建一个新的FLA,然后在舞台上绘制一些内容。
    2.  选中内容按下F8将其转换为元件。
    3.  在转换元件的对话框中,输入元件的名称,并选择元件类型为影片剪辑(MovieClip)。
    4.  选择为ActionScript导出。
    在这一点上,在之前版本的Flash中,你将获得一个自动生成的链接ID,你也可以选择输入一个类。
    在Flash CS3中,链接ID文本域被禁止了,类文本域强制要求输入并且添充了一个默认值。它也是一个新的文本域,基于类,它预置的是flash.display.MovieClip。你可以将它改为扩展影片剪辑或精灵(sprite)的其它类。
    输入你想要的类的名称。不用担心你还没有创建这个类。然后点击“OK”。这里会比较有趣。因为Flash不能找到你指定名称的类,它将在编译时自动生成一个类。这并不意味着你可以找到Flash自动创建的一个ActionScirpt类,但是它会在你的SWF中以字节代码(bytecode)的形式创建一个基于精灵(sprite)或影片剪辑的新类。这个类实际上不能象扩展其它基础类的子类一样,但是它将会链接到你库中的元件。

    现在,假设你在刚才说到的对话中输入的类名为Ball。在你的文档类(document Class),或在时间线上,你可以书写如下代码:
    代码:

    var  ball:Ball  =  new  Ball();
    addChild(ball);


    这样库中的元件应会在舞台上被创建,就是象以前AS2中的attachMovie方法。
    如果你想将库中的影片剪辑内容贴加到影片中,这是一个非常好的方法。但是比只是简单的接受自动生成类的更好方法是,你可以指定一个自已编写的真实的类路径,可以为你的元件加入一些函数定义。现在让我们跳出Flash IDE,回到下一个范例的类中来。
    现在,我们将重新来看前面刚刚给出的重设父级(reparenting)的范例,那里的一些复制可以被简化为另一个类。在那个范例中,我们创建了一个名为parent1的精灵并在它的内部绘制了一个盒子如下代码:
    代码:

    parent1.graphics.lineStyle(1,  0);
    parent1.graphics.drawRect(-50,  -50,  100,  100);

    我们接着创建了另外一个精灵(sprite),parent2,在它的内部也用同样的代码绘制了同样的盒子。尽管这是一个很简单的例子,但是它可以清晰的显示出精灵的子类是怎样应用的。首先,我们创建一个扩展精灵(sprite)名为ParentBox 的类。在这个类中,我们编写编制盒子子代码。
    代码:

    package  {
    import  flash.display.Sprite;

    public  class  ParentBox  extends  Sprite  {
    public  function  ParentBox()
    {
    init();
    }
    private  function  init():void
    {
    graphics.lineStyle(1,  0);
    graphics.drawRect(-50,  -50,  100,  100);
    }
    }
    }

    然后我们将告诉类创建两个ParentBox即可,而不再是两个精灵(spirte)了。

    代码:

    package  {
    import  flash.display.Sprite;
    import  flash.events.MouseEvent;

    public  class  Reparenting2  extends  Sprite  {
    private  var  parent1:ParentBox;
    private  var  parent2:ParentBox;
    private  var  ball:Sprite;

    public  function  Reparenting2()  {
    init();
    }
    private  function  init():void  {
    parent1  =  new  ParentBox();
    addChild(parent1);
    parent1.x  =  60;
    parent1.y  =  60;

    parent2  =  new  ParentBox();
    addChild(parent2);
    parent2.x  =  170;
    parent2.y  =  60;

    ball  =  new  Sprite();
    parent1.addChild(ball);
    ball.graphics.beginFill(0xff0000);
    ball.graphics.drawCircle(0,  0,  40);
    ball.graphics.endFill();
    ball.addEventListener(MouseEvent.CLICK,  onBallClick);
    }
    public  function  onBallClick(event:MouseEvent):void
    {
    parent2.addChild(ball);
    }
    }
    }


    作为parentBox的实例,他们仍是精灵(Sprite),因此可以在它们中加入子对象。它们也可以使用新的绘制图形的init方法。这是一个很小的例子,但是希望你能够理解它,当你继续向下看这本书时,你会看到许多更为复杂的范例。
    你也许想要针对此例加入一个Ball类,这样做不能够在减少你的复制操作了,但是会使你的类变得更为复杂,一个比较好的主意是将某些可分离的功能定义成不同的类,而不应是把任何不论有多小的东西都放入到一个单独的类中。这种方式也是最值得的推荐的。实际上,在接下本书的内容中,你很快就可以创建一个你需要用到的Ball类了。

    2.7用户交互操作

    最后,我们来看用户交互,可能这就是你要阅读本书的原因之一。除此之外,如果本书没有使用交互或在影片中的一些动态输入,你也许要使用的就是补间(tween)了。
    实际上,我们在前面的章节上并不是一点也没有讨论这部分的内容。用户交互是基于用户事件,它们产生于鼠标事件和键盘事件。让我们快速的过一遍各种用户事件和它们的处理者(handler)。

    2.7.1鼠标事件

    鼠标事件在AS3中已经发生了激动人心的改变。在AS2中,影片剪辑自动的侦听所有的鼠标事件。现在任何对象都明确的加入自身做为一个侦听者。另外,在AS3中要响应鼠标事件,需要鼠标的光标停放在可视的显示对象(display object)内容上。这一点不同于AS2,在AS2中的mouseUp,mouseDown和mouseMove对于任何影片剪辑都会响应,而不管鼠标的光标是否已经定好位置。AS3中的mouseUp和mouseDown事件现在等同于AS2中的onPress和onRelease。
    鼠标事件的名称被定成字符串,这在前面的内容中我们已经提到过,最好的方法是使用MouseEvent的属性以保证不会出错。下面是MouseEvent类中可用的鼠标事件:
    CLICK
    DOUBLE_CLICK
    MOUSE_DOWN
    MOUSE_MOVE
    MOUSE_OUT
    MOUSE_OVER
    MOUSE_UP
    MOUSE_WHEEL
    ROLL_OUT
    ROLL_OVER
    这些属性自身名称就是很好的解释。如果要感觉一下他们,你可以创建和编译下面的类,它将trace出精灵(sprite)上发生的每一个鼠标事件。

    代码:

    package  {
    import  flash.display.Sprite;
    import  flash.events.MouseEvent;

    public  class  MouseEvents  extends  Sprite  {
    public  function  MouseEvents()  {
    init();
    }
    private  function  init():void
    {
    var  sprite:Sprite  =  new  Sprite(); addChild(sprite);
    sprite.graphics.beginFill(0xff0000); sprite.graphics.drawCircle(0,  0,  
    50); sprite.graphics.endFill();
    sprite.x  =  stage.stageWidth  /  2;
    sprite.y  =  stage.stageHeight  /  2;

    sprite.addEventListener(MouseEvent.CLICK,  onMouseEvent);
    sprite.addEventListener(MouseEvent.DOUBLE_CLICK, onMouseEvent);
    sprite.addEventListener(MouseEvent.MOUSE_DOWN, onMouseEvent);
    sprite.addEventListener(MouseEvent.MOUSE_MOVE, onMouseEvent);
    sprite.addEventListener(MouseEvent.MOUSE_OUT, onMouseEvent);
    sprite.addEventListener(MouseEvent.MOUSE_OVER, onMouseEvent);
    sprite.addEventListener(MouseEvent.MOUSE_UP, onMouseEvent);
    sprite.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseEvent);
    sprite.addEventListener(MouseEvent.ROLL_OUT, onMouseEvent);
    sprite.addEventListener(MouseEvent.ROLL_OVER, onMouseEvent);
    }
    public  function  onMouseEvent(event:MouseEvent):void
    {
    trace(event.type);
    }
    }
    }


    注意,这个类对每一种事类型使用了同一个处理者(handler),只是简单的trace出被发送出来的事件类型。

    2.7.2鼠标位置

    除了鼠标事件,还有两个重要的属性是可能的,它们是来自文档类(document class)或其它显示对象(display object)用来检测当前鼠标光标的位置:mouseX和mouseY。注意他们是影片剪辑的属性,返回是鼠标相对于剪辑注册点的位置。例如,如果你有一个名为sprite的精灵在舞台上的位置为100,100,鼠标光标的位置在150,250,你会得到下面的结果:
    mouseX is 150.
    mouseY is 250.
    sprite.mouseX is 50.
    sprite.mouseY is 150.
    注意影片剪辑是如何得出鼠标光标在它自身上的位置的。

    2.7.3键盘事件

    键盘事件是另一部分在AS3中被整理的部分。例如,在AS2中,影片剪辑自动的侦听键盘事件,但是它们只在特点的环境下才会响应事件。因些最好的办法是加入一个影片剪辑做为侦听者,但是当影片接受多个事件而不只是单单接收键盘事件时,这种方法会失效。接着,AS2组件架构的一大部分是用来处理键盘的交互---关系到Flash播放器底层的架构:tab管理,焦点管理,文本域中的回车和tab键,等等。
    现在我们说情况要好的很多
    键盘事件的名称,就象鼠标事件一样,被定义成字符串,但他们仍是KeyboardEvent类的属性。他们只有两个:
       KEY_DOWN
       KEY_UP
    你可以在一个指定的对象上侦听键盘事件,就象我们前面讲到的侦听鼠标事件一样。为了做到这一点,然而,你需要先使对象获得焦点以使它可以捕获那些事件。你可以象下面这样书写:
    stage.focus  =  sprite;
    而在许多案例中,只记得侦听键盘事件却忽视的它的焦点。要做到这一点,你可以直接在舞台上侦听键盘事件。下面是一个范例示范:
    代码:

    package  {
    import  flash.display.Sprite;
    import  flash.events.KeyboardEvent;

    public  class  KeyboardEvents  extends  Sprite  {
    public  function  KeyboardEvents()  {
    init();
    }
    private  function  init():void  {
    stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyboardEvent);
    stage.addEventListener(KeyboardEvent.KEY_UP, onKeyboardEvent);
    }
    public  function  onKeyboardEvent(event:KeyboardEvent):void  {
    trace(event.type);
    }
    }
    }


    2.7.4键盘代码

    通常,你想知道的并不只是一个键子被按下去或放出,而是想知道它是哪一个键子。有两种方法可以读取键盘事件函数中的信息。
    在之前我们讨论事件的过程中,我说过一个事件处理者(handler)接收传过来的一个事件对象,这个事件对象中包含着刚刚发生的事件的数据信息。在一个键盘事件中,有两个属性与事件中的按键有关:charCode和keyCode。
    charCode属性给出的是真实的描述键子的字符。例如,如果用户在键盘上按下“a”键,charCode将包含这个字符串“a”。如果用户同时也按下了Shift键,charCode将包含的是“A”。
    KeyCode包含的是描述按下键子的物理键值。如果一个用户按下“a”键,keyCode将包含数值65,会忽视其它同时按下的按键。如果用户同时按下Shift和“a”,你需要两个键盘事件:一个是Shift(keyCode 16)和另一个是“a”(65)。
    flash.ui.Keyboard类也有一些属性可用于一些数字键,因此你不需要记住它们,例如,Keyboard.SHIFT 等于数值16,因些你可检测keyCode是否等于Keyboard.SHIFT来发现Shift键是否被按下。这一章中的最后一个例子示范如下:

    代码:

    package  {
    import  flash.display.Sprite;
    import  flash.events.KeyboardEvent;
    import  flash.ui.Keyboard;

    public  class  KeyCodes  extends  Sprite  {
    private  var  ball:Sprite;

    public  function  KeyCodes()  {
    init();
    }
    private  function  init():void  {
    ball  =  new  Sprite();
    addChild(ball);
    ball.graphics.beginFill(0xff0000);
    ball.graphics.drawCircle(0,  0,  40);
    ball.graphics.endFill();
    ball.x  =  stage.stageWidth  /  2;
    ball.y  =  stage.stageHeight  /  2;
    stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyboardEvent);
    }
    public  function  onKeyboardEvent(event:KeyboardEvent):void  {
    switch(event.keyCode)  {
    case  Keyboard.UP  :
    ball.y  -=  10;
    break;

    case  Keyboard.DOWN  :
    ball.y  +=  10;
    break;

    case  Keyboard.LEFT  :
    ball.x  -=  10;
    break;

    case  Keyboard.RIGHT  :
    ball.x  +=  10;
    break;

    default:
    break;
    }
    }
    }
    }



    还一点需要知道的是当你在Flash创作环境中测试你的影片时,Flash IDE会侦听一些键子来操作IDE自身。如Tab键,所有的功能键,和一些指定了快捷键的菜单,这些键子不会在你的测试影片中被接收。你可以通过选择控制菜单(control>Disable Keyboard Shortcuts)然后选择禁止快捷键来解决。测试时就象真正工作在浏览器中一样。

    总结

    这一章覆盖了所有关于ActionScript动画所需要基础。你现已经知道了帧循环,事件,侦听者,处理者,和显示列表。我也介绍了类,对象和基本的用户交互。这是许多有用的资料!如果有些地方还有点模糊不用担心。当进入到指定的技术内容时,我会尽量详细讲解它们,并且你可以随时回到这里,巩固任何概念。至少,现在你已经熟悉了这些术语和概念,你可以准备继续向前了。
  • 相关阅读:
    linux上用selenium登录新浪微博,获取用户关注的用户id
    JS、Python对字符串的编码函数
    在ubuntu系统下装hadoop
    windows下python3.x的安装与使用
    python多线程、多进程、协程的使用
    python简单操作redis
    操作系统基础知识
    排序算法汇总
    网易的突然袭击
    小红书视频面试
  • 原文地址:https://www.cnblogs.com/chinatefl/p/1218155.html
Copyright © 2011-2022 走看看