强制操作从$ .each循环排队

时间:2010-09-16 09:22:07

标签: javascript jquery triggers

我使用jquery为html元素(卡片)制作动画。我需要为交易动作制作动画('一个是你的,一个是我,一个是你,一个是我......')所以想要在下一个开始之前完全动画(移动位置)。我在$ .each函数中创建卡片并从那里调用动画(以避免不必要的循环)。当卡片添加到页面时,动画开始,但循环然后移动到下一张卡片而不等待动画完成。这使得所有卡片看起来在完全相同的时间而不是顺序地动画。如何让循环等待动画回调?这可以用触发器来完成吗?我可以手动排队项目吗?

我的(错误的)代码的缩减版本:

var card = [
  { id:1, pos:{ x:100, y:100 } },
  { id:2, pos:{ x:150, y:105 } },
  { id:3, pos:{ x:200, y:110 } }
];

$.each(card, function() {
  $('#card_' + this.id).animate({ top:this.pos.y, left:this.pos.x });
});

演示@ http://jsbin.com/akori4

4 个答案:

答案 0 :(得分:4)

您无法在JavaScript循环中执行此操作,您必须使用animate调用上的回调参数来触发下一张卡片的动画。像这样:

var card = [
    { id:1, pos:{ x:100, y:100 } },
    { id:2, pos:{ x:150, y:105 } },
    { id:3, pos:{ x:200, y:110 } }
];

doOne(0);

function doOne(index) {
    var thisCard = card[index];
    if (thisCard) {
        $('#card_' + thisCard.id).animate({
            top:    thisCard.pos.y,
            left:   thisCard.pos.x
        }, function() {
            doOne(index + 1);
        });
    }
}

Here's a live example当然,我将所有这些都包含在一个函数中,以避免创建不必要的全局符号。

答案 1 :(得分:2)

您可以使用.delay(),如下所示:

$.each(card, function(i) {
  $('#card_'+this.id).delay(i*400).animate({ top:this.pos.y, left:this.pos.x });
});

Here's your updated/working demo

每个动画(默认情况下)需要400毫秒,$.each()回调的第一个参数是索引,因此第一个延迟0 * 400,第二个1 * 400等...有效运行它们一个接一个。

此外,如果您 需要那些x / y格式变量,您可以将它们存储为top / left并传递那些动画属性直接,如下:

var card = [
  { id:1, pos:{ left:100, top:100 } },
  { id:2, pos:{ left:150, top:105 } },
  { id:3, pos:{ left:200, top:110 } }
];

$.each(card, function(i) {
  $('#card_'+this.id).delay(i*400).animate(this.pos);
});

答案 2 :(得分:1)

这是另一种方法:

var card = [
    {elem: $('#card_1'), id:1, pos:{ x:100, y:100 } },
    {elem: $('#card_2'), id:2, pos:{ x:150, y:105 } },
    {elem: $('#card_3'), id:3, pos:{ x:200, y:110 } }
];

(function loop(arr, len){
    if(len--){      
        arr[len].elem.animate({top: arr[len].pos.y, left: arr[len].pos.x}, 400, function(){
           loop(arr, len);
        });     
    }
}(card.reverse(), card.length));

行动中:http://jsbin.com/akori4/6/edit

答案 3 :(得分:0)

这可能会使正常的回调变得混乱,因为每个动画需要在其回调中调用下一个。当然,您可以使用计时器或延迟来创建暂停,但这并不能保证在下一个动画开始之前完整动画完成。如果动画花费的时间少于超时时间,则每个动画之间可能会有一个暂停。

另一种选择是研究承诺和期货。虽然我没有执行动画,但我的应用程序具有必须按特定顺序处理的逻辑。我一直在使用FuturesJS库来帮助简化操作。起初它可能看起来令人生畏,但它确实非常强大。看一下.chainify()方法。

我意识到这对你的简单用例来说可能有些过分,但我相信了解Promise是值得的。