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

发布于 2024-09-24 03:49:04 字数 614 浏览 0 评论 0原文

我正在使用 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

I am animating html elements (cards) using jquery. I need to animate a dealing action ('one you for you, one for me, one you you, one for me...') so want the cards to fully animate (move position) before the next one starts. I am creating the cards in a $.each function and calling the animation from there (to avoid looping again unnecessarily). When the card is added to the page the animation starts but the loop then moves on to the next card without waiting for the animation to finish. This makes all the cards appear to animate at exactly the same time rather than sequentially. How do I make the loop wait for the animation callback? Could this be done with triggers? Could I manually queue the items?

A cut down version of my (erroneous) code:

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 });
});

Demo @ http://jsbin.com/akori4

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

滿滿的愛 2024-10-01 03:49:04

您不能在 JavaScript 循环中执行此操作,必须在 animate< 上使用回调参数/code>调用触发下一张卡片的动画。像这样的东西:

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);
        });
    }
}

这是一个实例 当然,我会将所有这些包装在一个函数中以避免创建不必要的全局符号。

You can't do this in the JavaScript loop, you have to use the callback parameter on the animate call to trigger the animation of the next card. Something like this:

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 Naturally I'd have all this wrapped in a function to avoid creating unnecessary global symbols.

最舍不得你 2024-10-01 03:49:04

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

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

这是您的更新/工作演示

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

另外,如果您不需要这些 x/y 格式变量,您可以将它们存储为 top/< code>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);
});

You can use .delay(), like this:

$.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.

Each animation (by default) takes 400ms, and the first parameter to the $.each() callback is the index, so the first is delayed 0*400, the second 1*400, etc...effectively running them one after the other.

Also if you don't need those x/y format variables, you can store them as top/left and pass those animation properties directly, like this:

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);
});
动次打次papapa 2024-10-01 03:49:04

这是另一种方法:

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

Here's another approach:

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));

In action: http://jsbin.com/akori4/6/edit

莫相离 2024-10-01 03:49:04

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

另一种方法是研究 Promises 和 Futures。尽管我不执行动画,但我的应用程序具有必须按特定顺序处理的逻辑。我一直在使用 FuturesJS 库来帮助简化事情。乍一看可能有点吓人,但它确实非常强大。看一下 .chainify() 方法。

我意识到这对于您的简单用例来说可能有点过分了,但我认为了解 Promise 是值得的。

This could get messy with normal callbacks, as each animation then needs to call the next in its callback. Of course you could use a timer or delay to create a pause, but this doesn't guarantee the full animation completes before the next one starts. And there could be a pause between each animation if the animation takes less time than your timeout.

An alternative is to look into Promises and Futures. Although I'm not performing animations, my applications have logic that must be processed in a certain order. I've been using the FuturesJS library to help simplify things. It may look intimidating at first, but it is really very powerful. Take a look at the .chainify() method.

I realize this is probably overkill for your simple use case, but knowing about Promises is something I believe is worthwhile.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文