【问题标题】:Best way to execute a function after exactly one frame?在一帧之后执行功能的最佳方法?
【发布时间】:2009-03-23 00:07:18
【问题描述】:

对于 Flash Player 9+ 的 ActionScript3,在恰好一帧之后调用“一次性”函数的最佳方式是什么?

我知道 Timer 类及其用途,以及 Flex UIComponents 上的 callLater 方法(浏览源代码,在这种情况下看起来效率不高)。我也知道 setTimeout(在 flash.utils 中)。

Timer 类和 setTimeout 实用程序都是基于时间的,那么我们如何保证我们的函数会在一帧之后被调用?

从我有限的测试来看,传递给 setTimeout 的函数似乎只在至少一帧后执行(尝试将延迟设置为 0)。但这不能保证。

当然,我们可以从 DisplayObject 监听 Event.ENTER_FRAME 事件,但这对于一次性延迟函数调用来说似乎有点过头了。

【问题讨论】:

    标签: apache-flex actionscript-3 flash timing


    【解决方案1】:

    Flex 旨在抽象出 Flash Player 的基于帧的特性,因此您不会找到太多可以帮助您解决问题的方法。最好的方法是按照您的建议收听 ENTER_FRAME 。如果这太过分了(我不确定你为什么这么认为),你可以创建一个辅助类,它以 DisplayObject 和 Function 作为参数,它会自动为你添加/删除 ENTER_FRAME 事件监听器。

    public class NextFrameCommand() {
    
        private var functionToCall : Function;
    
        public function NextFrameCommand(dObj: DisplayObject, func : Function) {
            functionToCall = func;
        }
    
        public function start() : void {
            dObj.addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
    
        private function onEnterFrame(e : Event) : void {
            e.target.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
            functionToCall.call();
        }
    
    }
    

    我还没有测试过那个代码,但希望你能明白......

    【讨论】:

    • 糟糕,在同一时间发布,我认为最好的是您的结构(可重用性),但在我的示例中自动实例化一个虚拟精灵(我只是想快速说明这个想法)。
    【解决方案2】:

    使用 Theo 和 brd6644 提供的解决方案,我带来了这个。它允许多个函数(带参数)在下一帧按顺序排队执行。

    public class DelayedFunctionQueue
    {
        protected var queue:Array;
        protected var dispatcher:Sprite;
    
        public function DelayedFunctionQueue()
        {
            queue = new Array();
            dispatcher = new Sprite();
        }
    
        public function add( func:Function, ... args ):void
        {
            var delegateFn:Function = function():void
            {
                func.apply( null, args );
            }
            queue.push( delegateFn );
            if ( queue.length == 1 )
            {
                dispatcher.addEventListener( Event.ENTER_FRAME, onEF, false, 0, true );
            }
        }
    
        protected function onEF( event:Event ):void
        {
            dispatcher.removeEventListener( Event.ENTER_FRAME, onEF, false );
            queue = queue.reverse();
            while ( queue.length > 0 )
            {
                var delegateFn:Function = queue.pop();
                delegateFn();
            }
        }
    }
    

    可能对某人有用。

    【讨论】:

      【解决方案3】:

      一种方法是查看您的项目设置为每秒多少帧,并让 setTimeout 函数在该设置内延迟 1 帧时间。

      因此,如果您的项目设置为每秒 24 帧,您会在 setTimeout 中延迟 42 毫秒。

      【讨论】:

        【解决方案4】:
        var timerSprite:Sprite = new Sprite();
        
        timerSprite.addEventListener(Event.ENTER_FRAME, oneFrameHandeler);
        
        function oneFrameHandeler(e:Event):void
        {
           timerSprite.removeEventListener(Event.ENTER_FRAME, oneFrameHandeler);
           timerSprite = null;
        
           trace("one frame later!")
        }
        

        【讨论】:

          【解决方案5】:

          ENTER_FRAME 并不过分——这样的事情很简单

          addEventListener(Event.ENTER_FRAME, function(e:Event):void
          {
              removeEventListener(Event.ENTER_FRAME, arguments["callee"]);
              onceOffFunction();
          }
          

          【讨论】:

          • 这个答案没有添加任何东西,并且几年前已经由其他人提供并且答案被接受了。您要添加什么尚未说过的内容?
          猜你喜欢
          • 2011-02-19
          • 1970-01-01
          • 1970-01-01
          • 2014-11-03
          • 2021-06-02
          • 2015-04-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多