Принудительное действие в очередь из цикла $ .each - PullRequest
1 голос
/ 16 сентября 2010

Я анимирую элементы html (карты), используя jquery. Мне нужно оживить раздающее действие («один ты для тебя, один для меня, один ты, один для меня ...»), поэтому я хочу, чтобы карты полностью оживили (позиция перемещения) до начала следующего. Я создаю карты в функции $ .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 ]

4 голосов
/ 16 сентября 2010

Вы не можете сделать это в цикле 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);
        });
    }
}

Вот живой пример Естественно, я бы все это обернул в функцию, чтобы избежать создания ненужных глобальных символов.

2 голосов
/ 16 сентября 2010

Вы можете использовать .delay(), например:

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

Вот ваше обновленное / рабочее демо .

Каждая анимация (по умолчанию) занимает 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);
});
1 голос
/ 16 сентября 2010

Вот еще один подход:

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

0 голосов
/ 16 сентября 2010

Это может привести к путанице с обычными обратными вызовами, поскольку каждая анимация должна вызывать следующую в своем обратном вызове. Конечно, вы можете использовать таймер или задержку для создания паузы, но это не гарантирует, что полная анимация завершится до начала следующей. И между каждой анимацией может быть пауза, если анимация занимает меньше времени, чем ваш тайм-аут.

Альтернатива - заглянуть в Обещания и Фьючерсы. Хотя я не выполняю анимацию, в моих приложениях есть логика, которая должна обрабатываться в определенном порядке. Я использовал библиотеку FuturesJS , чтобы упростить процесс. Поначалу это может показаться пугающим, но это действительно очень мощно. Взгляните на метод .chainify().

Я понимаю, что это, вероятно, излишне для вашего простого варианта использования, но знание Обещаний - это то, что я считаю стоящим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...