MovieClip的结束事件监听器是什么?

9

有人可以建议最好的方法来触发一个函数当一个MovieClip动画结束时吗?我想使用事件侦听器来处理这个问题,但不确定最佳方法是什么。谢谢。Paul


1
目前正在处理类似的问题。最简单的方法是使用ENTER_FRAME事件监听器,检查当前帧是否为最后一帧(例如:function checkLastFrame(event:Event):void{ trace(currentFrame == totalFrames); }),但根据情况的简单或复杂程度,您可能会发现以下资源很有用:http://www.adobe.com/devnet/flash/articles/timelinewatcher.html、http://www.bytearray.org/?p=603、http://www.tink.ws/blog/framelabelmovieclip-uiframelabelmovieclip/。 - George Profenza
为什么不能在最后一帧触发事件? - The_asMan
@The_asMan 或者甚至在最后一帧分派一个事件,然后在其他地方监听它。 - Marty
1
我从as2的角度来看待这个问题 - 因此,从最后一帧触发事件是我首先想到的事情,但我无法弄清楚如何从动态加载的movieclip中触发根目录中的函数。 - Dancer
我经常想知道为什么Flash没有像视频播放完成时那样内置此事件。 - jhocking
8个回答

11

有几种方法可以实现这个目标:

  1. 在动画的最后一帧中直接调用该函数。
  2. 在函数的最后一帧上派发事件并在其他地方侦听它。
  3. 较为冗长但有效 / 整洁 / 建议的方法。

关于第三点,我建议您为对象创建一个基类。这样,您就可以将相同的逻辑应用于多个正在执行动画的元素。

像这样:

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

    public class AnimatingObject extends MovieClip
    {
        // constants
        public const ANIMATION_COMPLETE:String = "animation_complete";

        /**
         * Constructor
         */
        public function AnimatingObject()
        {
            addEventListener(Event.ENTER_FRAME, _handle);
        }

        /**
         * Called on dispatch of Event.ENTER_FRAME
         */
        private function _handle(e:Event):void
        {
            if(currentFrame == totalFrames)
            {
                var evt:Event = new Event(ANIMATION_COMPLETE);
                dispatchEvent(evt);
            }
        }
    }
}

现在我们可以监听"animation_complete"事件并相应地处理。

package
{
    import flash.events.Event;

    public class MyAnimatingObject extends AnimatingObject
    {
        /**
         * Constructor
         */
        public function MyAnimatingObject()
        {
            addEventListener(ANIMATION_COMPLETE, _lastFrame);
        }

        /**
         * Called on dispatch of AnimatingObject.ANIMATION_COMPLETE
         */
        private function _lastFrame(e:Event):void
        {
            trace("i'm done");
        }
    }
}

3

我已经有一段时间没有使用Flash了。现在我主要使用Flex,但这应该也可以用。
使用enterFrame事件会浪费大量资源,而创建自定义事件类并不必要。 在最后一帧上添加以下内容:

dispatchEvent(new Event("INSERTSTUPIDEVENTNAMEHERE"));

在你的“根目录”代码中
movieInstanceName.addEventListener( "INSERTSTUPIDEVENTNAMEHERE", someCallBackFunction );

function someCallBackFunction ( e:Event ):void{
  trace( "Last frame hit");
}

如果您在Flash中将代码放在时间轴上,那么这个答案是可行的,但您可能无法访问原始的.fla文件,甚至不想将代码放在时间轴上,因为有时会很困惑。此外,我不会将enterFrame事件称为资源的“巨大”使用。 - jhocking

2

通过使用ENTER_FRAME监听器,您可以判断MovieClip是否已经播放到结尾;然后,您可以将其进一步包装在Wrapper类中,以便为您执行监视:

public class EndOfMovieClipEventDispatcher extends EventDispatcher
{
    private var target : MovieClip;
    private var endReachedEvent : String;

    public function EndOfMovieClipEventDispatcher(target : MovieClip, endReachedEvent : String = "complete") {
        this.target = target;
        this.endReachedEvent = endReachedEvent;
        target.addEventListener(Event.ENTER_FRAME, onEnterFrameEvent, false, 0, true);
    }

    public function destroy() : void {
        target.removeEventListener(Event.ENTER_FRAME, onEnterFrameEvent);
    }

    private function onEnterFrameEvent(event : Event) : void
    {
        if (target.currentFrame == target.totalFrames) {
            dispatchEvent(new Event(endReachedEvent));
        }
    }
}

使用方法非常简单;由于使用了弱事件监听器,因此destroy()的调用是可选的,但如果您已经完成了操作,则建议调用它 :)

new EndOfMovieClipEventDispatcher(myMovieClip).addEventListener(Event.COMPLETE, onMovieClipCompleteEvent);
myMovieClip.play();

0

我不认为在影片剪辑结束时有事件广播,你可以在动画的最后一帧运行一个脚本来执行你想要的操作。如果你真的想使用事件,影片剪辑的最后一帧可以执行一个脚本,利用dispatchEvent()发送自定义事件,这样就能接收到。

我无法确定你是否使用过事件处理程序,所以这里有一个教程(我不太擅长解释,抱歉!): http://edutechwiki.unige.ch/en/ActionScript_3_event_handling_tutorial

至于dispatchEvent(): http://www.actionscript.org/resources/articles/204/1/Using-EventDispatcher/Page1.html


0

你可以使用一个enterframe监听器来检查电影剪辑的currentFrame是否等于totalFrames,如果相等,则触发你自己创建的自定义事件(如TimelineComplete)。

另一种选择是创建一个小组件来触发你的自定义TimelineComplete事件,并将该组件放置在任何你想要监视的动画的最后一帧上。这将允许你在未来更有创意地添加延迟触发事件等功能。

你有几个选择,但我认为都不是理想的选择,但它们确实有效,如果做得好,它们不会变得难以控制。唯一不建议的是在最后一帧上添加一点代码,因为随着时间的推移,这会变得非常难以跟踪。


0

仅检查currentFrametotalFrames不足以处理具有多个场景的MovieClip。您还必须检查它是否在最后一个场景。

function isAtLastFrame(mc:MovieClip):Boolean
{
  return currentScene.name == mc.scenes[mc.scenes.length - 1].name && currentFrame == currentScene.numFrames;
}

0

如果寻找最短的解决方案,我认为应该是:

        mc.addFrameScript(mc.totalFrames - 1, function():void 
        {
            trace("end of mc");
        });

0

您可以创建一个自定义的MovieClip类,当电影剪辑对象处于最后一帧时,它会分派一个事件。然后,您可以将自定义的MovieClip类作为您的电影剪辑动画的基类:

CustomMovieClip.as:

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

    public class CustomMovieClip extends MovieClip
    {
        private var _isLastFrame:Boolean;

        public function get isLastFrame():Boolean { return _isLastFrame }

        public function CustomMovieClip()
        {
            init();

        }// end function

        private function init():void
        {
            addEventListener(Event.ENTER_FRAME, onEnterFrame);

        }// end function

        private function onEnterFrame(e:Event):void
        {
            if (!_isLastFrame)
            {
                if (currentFrame == totalFrames) 
                {
                    dispatchEvent(new TimelineEvent(TimelineEvent.LAST_FRAME));
                    _isLastFrame = true;

                }// end if

            }
            else 
            {
                if (currentFrame != totalFrames) _isLastFrame = false;

            }// end else

        }// end function

    }// end class

}// end package

TimelineEvent.as:

package events
{   
    import flash.events.Event;

    public class TimelineEvent extends Event 
    {
        public static var LAST_FRAME:String = "lastFrame";

        public function TimelineEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) 
        { 
            super(type, bubbles, cancelable);

        }// end function

        public override function clone():Event 
        { 
            return new TimelineEvent(type, bubbles, cancelable);

        }// end function

    }// end class

}// end package

Main.as(文档类):

package 
{
    import display.CustomMovieClip;
    import events.TimelineEvent;
    import flash.display.Sprite;
    import flash.events.Event;

    public class Main extends Sprite 
    {
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);

        }/// end function

        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            var customMovieClip:CustomMovieClip = new CustomMovieClip();
            customMovieClip.addEventListener(TimelineEvent.LAST_FRAME, onCustomMovieClipLastFrame);
            customMovieClip.play();

        }// end function

        private function onCustomMovieClipLastFrame(e:TimelineEvent):void
        {
            var customMovieClip:CustomMovieClip = CustomMovieClip(e.target);
            customMovieClip.removeEventListener(TimelineEvent.LAST_FRAME, onCustomMovieClipLastFrame);

            trace(customMovieClip.isLastFrame); // output: true

        }// end function

    }// end class

}// end package

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接