使用ActionScript3 for Flash Player 9+,在一帧之后调用“一次性”功能的最好方法是什么?
我知道Timer类及它的用途,以及Flex UIComponents上的callLater方法(在这种情况下,浏览源代码看起来效率不高)。我也知道setTimeout(在flash.utils中)。
Timer类和setTimeout实用程序都是基于时间的,那么我们如何保证在一帧之后调用我们的函数呢?
从我的有限测试中看来,传递给setTimeout的函数似乎只在至少一帧之后执行(尝试将延迟设置为0)。但这不能保证。
当然,我们可以从DisplayObject监听Event.ENTER_FRAME事件,但这对于一次性延迟函数调用来说似乎有些过分。
答案 0 :(得分:3)
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();
}
}
我没有测试过那段代码,但希望你能得到这个想法......
答案 1 :(得分:1)
使用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();
}
}
}
可能对某人有用。
答案 2 :(得分:0)
一种方法是查看项目设置的每秒帧数,并让setTimeout函数在该设置中延迟1帧时间。
因此,如果您的项目设置为每秒24帧,则在setTimeout中延迟42毫秒。
答案 3 :(得分:0)
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!")
}
答案 4 :(得分:-2)
ENTER_FRAME并不过分 - 这样的事情很简单
addEventListener(Event.ENTER_FRAME, function(e:Event):void
{
removeEventListener(Event.ENTER_FRAME, arguments["callee"]);
onceOffFunction();
}