1

我正在尝试制作一个对象,它是一个影片剪辑,连续上下移动,并在它完成移动时打印它的 y 轴值。下面的代码工作正常。

var tweenUp:Tween = null, tweenDown:Tween = null;

function up():void {
    tweenUp = new Tween(person,"y",None.easeNone,person.y,person.y+20,1,true);
    tweenUp.addEventListener(TweenEvent.MOTION_FINISH, finishedUp);
}
function down():void {
    tweenDown = new Tween(person,"y",None.easeNone,person.y,person.y-20,1,true);
    tweenDown.addEventListener(TweenEvent.MOTION_FINISH, finishedDown);
}

function finishedUp(event:TweenEvent):void {
    trace(person.y);
    tweenUp.removeEventListener(TweenEvent.MOTION_FINISH, finishedUp);
    tweenUp = null;
    down();
}
function finishedDown(event:TweenEvent):void {
    trace(person.y);
    tweenDown.removeEventListener(TweenEvent.MOTION_FINISH, finishedDown);
    tweenDown = null;
    up();
}

up();

但是,我正在寻找一种将对象传递给侦听器的回调函数的解决方案。我尝试使用下面显示的方式,但它不起作用。

var tweenUp:Tween = null, tweenDown:Tween = null;
var functionFinishedUp:Function = null, functionFinishedDown:Function = null;

function up(object:MovieClip):void {
    tweenUp = new Tween(object,"y",None.easeNone,object.y,object.y+20,1,true);
    functionFinishedUp = finishedUp(object);
    tweenUp.addEventListener(TweenEvent.MOTION_FINISH, functionFinishedUp);
    tweenUp.removeEventListener(TweenEvent.MOTION_FINISH, functionFinishedUp);
    tweenUp = null;
}
function down(object:MovieClip):void {
    tweenDown = new Tween(object,"y",None.easeNone,object.y,object.y-20,1,true);
    functionFinishedDown = finishedDown(object);
    tweenDown.addEventListener(TweenEvent.MOTION_FINISH, functionFinishedDown);
    tweenDown.removeEventListener(TweenEvent.MOTION_FINISH, functionFinishedDown);
    tweenDown = null;
}

function finishedUp(object:MovieClip):Function {
    return function(event:TweenEvent):void {
        trace(object.y);
        down(object);
    }
}
function finishedDown(object:MovieClip):Function {
    return function(event:TweenEvent):void {
        trace(object.y);
        up(object);
    }
}

up(person);

它只是上升然后什么也不做,因为似乎监听器在添加后就被删除了。在侦听器完成其任务后,是否有任何好的解决方案可以删除具有参数传递的侦听器?

提前感谢您提供的任何帮助!

4

2 回答 2

3

如果您正在寻找一种在收到事件后立即删除事件侦听器的简单方法,您可以这样做:

function listener(event:Event):void
{
     // stop listening to the dispatcher for this event type
     EventDispatcher(event.target).removeEventListener(event.type, arguments.callee);
     // ...and do whatever else you need to do here
}

该行可用于任何事件侦听器。

另一种选择是使用信号(https://github.com/robertpenner/as3-signals)。他们有一种addOnce方法,只会听一次然后删除自己。

于 2013-02-02T11:24:51.510 回答
1

首先,我建议不要将object其用作变量的名称!尽管在技术上允许,但它在语义上没有意义,并且与保留的类名相似也无济于事Object

您的代码不起作用的原因是您在添加后立即删除事件处理程序 - 在它有机会被调用之前。您实际上不必删除侦听器,因为您希望每次完成相应的补间时都调用它们。如果您坚持每次迭代都附加和分离侦听器函数,则必须在侦听器函数本身中删除事件侦听器。当然,对于您正在创建和折腾的所有闭包,这会变得相当棘手。

事实上,您根本不需要闭包,因为tween对象在obj属性中引用了补间对象。另外,你只需要为每个目标人物创建一个up tween和一个down tween,然后就可以rewind()start()每个tween来回切换了。您可以使用几个 Dictionary 对象来跟踪哪个补间与哪个人一起使用,这些对象使用对象引用作为键。

这是一个概念证明,它person使用自己的补间集生成了 20 个 s——但只定义了两个处理程序,而且它们都不是闭包。我还结合upfinishedDown和:downfinishedUp

var upTweens:Dictionary = new Dictionary();
var downTweens:Dictionary = new Dictionary();

for(var i:uint = 0; i < 20; i++) {
    // Make a new Person
    var person:Person = new Person();
    person.y = 100;
    person.x = i * 20;
    addChild(person);

    // Create the tweens but stop them before they can play at all
    var top = person.y - 20;   // Up is -y in Flash
    var bottom = person.y;
    var upTween:Tween = new Tween(person, "y", None.easeNone, bottom, top, 1, true);
    upTween.stop();
    upTween.addEventListener(TweenEvent.MOTION_FINISH, onUpFinished);
    var downTween:Tween = new Tween(person, "y", None.easeNone, top, bottom, 1, true);
    downTween.stop();
    downTween.addEventListener(TweenEvent.MOTION_FINISH, onDownFinished);

    // Associate tweens with this person, and start it up!
    upTweens[person] = upTween;
    downTweens[person] = downTween;
    upTween.start();
}


function onUpFinished(e:TweenEvent):void {
    var upTween:Tween = Tween(e.currentTarget);
    var person:Person = Person(upTween.obj);
    var downTween:Tween = Tween(downTweens[person]);
    downTween.rewind();
    downTween.start();
}

function onDownFinished(e:TweenEvent):void {
    var downTween:Tween = Tween(e.currentTarget);
    var person:Person = Person(downTween.obj);
    var upTween:Tween = Tween(upTweens[person]);
    upTween.rewind();
    upTween.start();
}
于 2013-02-02T05:37:20.017 回答