AS3 - 多个addEventListener(KeyboardEvent) - 相同的键但不同的动作

时间:2016-11-10 14:26:35

标签: actionscript-3 keyboard-events addeventlistener

我希望,我的英语足够好,你理解我的解释和我的问题"!

Endgoal

使用单个键导航演示文稿,但操作不同......

  1. 在动画片段之间切换
  2. gotoAndPlay在Movieclip中
  3. 状态

    我刚刚开始使用AnimateCC演示模板构建演示文稿

    看起来像这样......

    Maintimeline

    AS3导航行动 和一个名为" slides_mc"

    的Movieclip
    // EVENTS
    stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_changeSlide);
    
    function fl_changeSlide(event:KeyboardEvent):void
    {
        if(event.keyCode == 37) // LEFT
        {
            fl_prevSlide();
        }
        else if (event.keyCode == 39) // RIGHT
        {
            fl_nextSlide();
        }
    }
    // END EVENTS
    
    
    
    // FUNCTIONS AND LOGIC
    function fl_prevSlide():void
    {
        if(slides_mc.currentFrame > 1)
        {
            slides_mc.gotoAndStop(slides_mc.currentFrame-1);
        }
    }
    function fl_nextSlide():void
    {
        if(slides_mc.currentFrame < slides_mc.totalFrames)
        {
            slides_mc.gotoAndStop(slides_mc.currentFrame+1);
    
        }
    }
    
    slides_mc.gotoAndStop(1);
    
    // END FUNCTIONS AND LOGIC
    
    stop();
    

    Movieclip slides_mc

    在slides_mc中,我在时间轴上有多个Movieclips(01,02,03,...),内容充满了内容。

    使用stop-Commands将一些Movieclip拆分为内部, 我喜欢用相同的 Keypress导航!

    构建概述

    Maintimeline
    -> Actions
    -> Movieclip (slides_mc)
    
    slides_mc
    -> multiple Movieclips (01, 02, 03)
    
    Movieclips (inside)
    -> Singlestop on the Endframe ... stop();   //on Keypress (next Slide)  or
    -> Multiplestops ... stop(),.... stop(),.... stop();  //on the same Keypress (next Frame)
    

    问题

    Movieclips之间的跳跃应该是这样的, 但我不知道该做什么, 在Movieclip里面, 使用相同的 Keypress调用另一个Action,就像这样

    stop();
    
    
    addEventListener(KeyboardEvent.KEY_DOWN, moveForward);
    
    function moveForward(event:KeyboardEvent):void
    
    {
        if(event.keyCode == 39)
    
        {
            gotoAndPlay (nextFrame);
        }
    }
    

    我想,实施起来很简单,但我阅读得越多, 我得到的问题越多;(

    重要!

    必须是,SAME Key,因为我使用只有两个按钮(向前,向后)的Handpresenter!

    我想的解决方案

    1. &#34;否决&#34;特定框架上的stage.EventListener
    2. Maintimeline / Actions上的例外(如果每个动画片段都需要)
    3. 删除/添加EventListener(stage.removeEventListener(KeyboardEvent.KEY_DOWN,fl_changeSlide); ...总是失败,没有找到fl_changeSlide的连接)
    4. 那么,有没有&#34;简单&#34; ;)方式,让这个工作,或者更容易,只是将Movieclip拆分为更多的Movieclip并对我已经拥有的脚本感到满意!?

      提前谢谢!

      编辑/进度1

      感谢您试图帮助......是的,听起来很简单, 但是因为我不是Coder,所以它只是试验&amp;我错了。

      现在,我尝试添加到我的主编中:

      stage.addEventListener("FirstOfFrames", CallBackFirst);
      
      function CallBackFirst (event:Event):void
      
      {
          trace("First");
          stage.removeEventListener(KeyboardEvent.KEY_DOWN, fl_changeSlide);
          stage.addEventListener(KeyboardEvent.KEY_DOWN, moveForward);
      }
      
      
      
      stage.addEventListener("LastOfFrames", CallBackLast);
      
      function CallBackLast (event:Event):void
      
      {
          trace("Last");
          stage.removeEventListener(KeyboardEvent.KEY_DOWN, moveForward);
          stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_changeSlide);
      }            
      

      并在第一帧的影片剪辑内:

      dispatchEvent(new Event("FirstOfFrames"));
      

      并在最后一帧:

      dispatchEvent(new Event("LastOfFrames")); 
      

      我正确的方式? ;)

      编辑/从第1步开始

      非常感谢BadFeelingAboutThis,这比我预期的要多得多(和代码需要:))!没有办法得到这个,只有试用和错误!

      但看起来,我做错了什么 - 现在它表现得像我有一个停止();在每一帧中。

      从头开始使用测试文件 我做了什么:

      1. 创建两个.as文件(Slide.as和NavigationEvent.as) 和复制&amp;将您的代码粘贴到其中

      2. 在同一个文件夹中创建一个新的* .fla

      3. Maintimeline 上的
      4. ,我复制&amp;在“操作”下粘贴键盘定义 并创建一个名为slides_mc

      5. 的Movieclip
      6. 在MC slides_mc中,我创建了一些其他MC(01,02,03),这些MC填充了几帧但没有任何代码(没有停止();)

      7. 在一个MC中,我在一些帧上设置了一些停靠点...... 对于这个MC我设置

        stage.dispatchEvent(new NavigationEvent(true)); //为前锋传递假,对于前锋传递真实(或没有)

      8. Maintimeline中的

        1. 最后,我编辑我的SymbolProperties(对于slide_mc和MCs 01,02,03),选中&#34;导出为ActionScript&#34;,为每个单MC定义一个Classname并输入Slide to Base类(通过Testoption确认确定)

        2. 尝试在Animate本身的测试环境中运行它(没有任何给定的错误), 直接导出为* .swf并导出为(Win&amp; Mac)投影仪, 始终使用相同的结果 - &gt;在每个MC(有或没有内容), 每个Keypress只移动1帧(向前和向后)

        3. 有没有提示,你可以给我,我可能忘记或做错了什么?

          PS:由于这篇文章变得越来越长,最好是删除&#34;帖子的开头&#34;,还是不重要?

2 个答案:

答案 0 :(得分:0)

我会说你在第3点走在正确的道路上。

对于执行冲突操作的同一事件,您有两个处理程序。所以你必须打开,而另一个是活跃的。 您无法从剪辑内部删除eventListener,因为您没有对处理函数的引用,因此您必须在主时间轴上执行此操作。

主时间轴上的

一旦触发就移除侦听器,并将slides_mc移动到下一张幻灯片。然后注册监听器以控制当前幻灯片。一旦你在幻灯片的末尾,删除它的监听器,并将(自定义事件)通知给你完成的主时间线,这样它就可以重新注册主要时间线并导航到下一张幻灯片......简单正确?

答案 1 :(得分:0)

以下是您可以完成自己喜欢的一种方法(

)。

使用自定义类(或两个)来最小化代码冗余。

在与.fla相同的文件夹中,创建一个新的文本文件,并将其命名为Slide.as。将以下代码粘贴到其中并保存。 (请查看代码注释,了解代码正在做什么的解释。)

package 
{
    import flash.display.DisplayObjectContainer;
    import flash.display.MovieClip;
    import flash.events.Event;

    public class Slide extends MovieClip
    {
        //static vars belong to the class as a whole, not an individual instance of a class.
        //this static var is used to determine if the most recent navigation event was forwards or backwards
        public static var forwards:Boolean = true;

        public var myPriority:int; //the priority this slide has to control navigation

        //this functions runs when the instance of this class is first created
        public function Slide() 
        {           
            this.addEventListener(Event.ADDED_TO_STAGE, addedToStage, false, 0, true);
            this.addEventListener(Event.REMOVED_FROM_STAGE, removedFromStage, false, 0, true);

            stop(); //let's stop by default, so you don't have to do it for each and every clip;

            //if moving backwards, go to the last frame
            if (!forwards) {
                this.gotoAndStop(this.totalFrames);
            }
        }

        //this function will run when the instnace of this class is added to a timeline
        private function addedToStage(e:Event):void {
            //find the first Slide parent (if any) and listen at 1 higher priority than it
            var p:DisplayObjectContainer = parent;
            while (p && p != stage) {
                if (p is Slide) {
                    myPriority = Slide(p).myPriority + 1;
                    break;
                }

                p = p.parent;
            }

            //listen for the navigate event, incriment priority everytime a slide is loaded so the most recently loaded slide is always in control
            stage.addEventListener("Navigate", navigateHandler, false, myPriority);

        }

        private function removedFromStage(e:Event):void {
            //remove the listener when this movie clip is unloaded from the screen
            stage.removeEventListener("Navigate", navigateHandler, false);
        }

        private function navigateHandler(e:NavigationEvent):void {
            //If the navigation is forward, and this movie clip isn't on the last frame
            if (e.isForward && this.currentFrame != this.totalFrames) {
                forwards = true;
                this.nextFrame();
                e.stopImmediatePropagation(); //cancel the event from reaching the others listening for it
            }

            //If the navigation is backwards, and this movie clip isn't on the first frame
            if (!e.isForward && this.currentFrame != 1) {
                forwards = false;
                this.prevFrame();
                e.stopImmediatePropagation(); //cancel the event from reaching the others listening for it
            }

            //if we didn't stop the propagation of the event, the next lowest priority listener will execute
        }

    }

}

再次创建一个新文件并将其称为NavigationEvent.as。粘贴此代码并保存:

package 
{
    import flash.events.Event;

    public class NavigationEvent extends Event 
    {
        public var isForward:Boolean = true;

        public function NavigationEvent(isForward_:Boolean = true) 
        {
            isForward = isForward_;
            super("Navigate", true, true);      
        }
    }
}

将自定义类附加到每个幻灯片资产

接下来,在您的Flash专业版库中,右键单击每个幻灯片MovieClip(包括slides_mc)并打开它的属性,然后选中&#39; 导出动作脚本&#39;复选框。 给它一个唯一的类名,然后在基类中放置Slide

Make your slides inherit all the code from the custom class

这将使幻灯片资产继承您在自定义类文件中粘贴的所有代码。

从用户输入创建导航事件

接下来,在您的主时间轴中,您希望随时想要导航更改(例如键盘或按钮点击)来创建导航事件。

stage.dispatchEvent(new NavigationEvent(false)); //pass false for back, true (or nothing) for forwards

以下是使用标准PowerPoint键盘快捷键的完整示例(大多数PowerPoint遥控器使用PageUp / Down作为键盘事件)

stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown);

function keydown(e:KeyboardEvent):void {
    switch(e.keyCode){
        //FORWARD KEYS
        case Keyboard.SPACE:
        case Keyboard.RIGHT:
        case Keyboard.DOWN:
        case Keyboard.PAGE_DOWN:
            stage.dispatchEvent(new NavigationEvent());
            break;

        //PREVIOUS SLIDE KEYS
        case Keyboard.BACKSPACE:
        case Keyboard.LEFT:
        case Keyboard.UP:
        case Keyboard.PAGE_UP:
            stage.dispatchEvent(new NavigationEvent(false));
            break;
    }
}