2015-07-02 3 views
0

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

function animate(){ 
    $ul.each(function(){ 
    $(this).find('li').each(function(){ 
      //animate block 
      $(this).animate({top:'-100%'},100,function(){ 
      $(this).css({top:'100%'}); 
      }); 
      //endblock 
     }); 
    }); 
} 

Как вы знаете, функции «живой блок» будут выполняться одновременно. Я хочу, чтобы они бежали последовательно. Как я могу это достичь?

Я прочитал jQuery 'offferred', 'Q' связать статью, но все еще запутанно.

Извините за мой английский.

--------- дополнение ------

Если я хочу, чтобы запустить функцию одушевленных несколько раз, что я должен делать?

ответ

0

Если вы хотите, чтобы избежать неловкого .queue()/.dequeue(), то вы можете построить цепочку обещание JQuery от коллекции JQuery ваших <li> элементов.

function animate($ul) { 
    var p = $.when(); //resolved starter promise 
    $("li", $ul).each(function(i, li) { 
     p = p.then(function() { 
      return $(li).animate({ top:'-100%' }, 100, function() { 
       return $(li).css({ top:'100%' }); 
      }).promise(); 
     }); 
    }); 
    return p; 
} 

Как только цепочка оседает, анимация будет происходить последовательно.

Более элегантно, вы можете расширить jQuery, чтобы иметь метод .reduce(), принятый от Array.prototype.

jQuery.fn.reduce = Array.prototype.reduce; 

Затем построить требуемое обещание цепи, вызывая .reduce() на коллекции JQuery.

function animate($ul) { 
    return $("li", $ul).reduce(function(p, li) {//wow, jQuery has a .reduce() method! 
     return p.then(function() { 
      //Here, perform the required animation and return a promise of its completion. 
      return $(li).animate({top:'-100%'}, 100, function() { 
       $(li).css({top:'100%'}); 
      }).promise(); 
     }); 
    }, $.when());//Resolved starter promise, ie p in the first iteration of .reduce() . 
} 

Этот шаблон стоит изучать, поскольку он имеет множество приложений.

В обоих примерах, внешний return позволяет цепи .then()animate(), где называется:

animate($("ul")).then(function() { 
    //do something when all the <li> animations have completed. 
}); 
0

Что-то, как это должно работать:

var last_deferred = $.Deferred(); 
last_deferred.resolve(); 

$ul.each(function(){ 
    $(this).find('li').each(function(){ 
     var deferred = $.Deferred(), 
      $that = $(this); 
     last_deferred.then(function() { 
      $that.animate({top:'-100%'},100,function(){ 
       $(this).css({top:'100%'}); 
       deferred.resolve(); 
      }); 
     }); 
     last_deferred = deferred; 
    }); 
}); 

Объяснение: здесь я использую 2 важные особенности отсроченных объектов .then и .resolve. Когда вы вызываете .resolve();, отложенный объект будет запускать все обработчики, назначенные ему через .then. Так что происходит, так это то, что я сначала определяю «фиктивный» отложенный, который я немедленно разрешаю. Если отложенный объект разрешен, добавление обработчика через .then автоматически запустит его. Так что же происходит в это

  1. last_deferred определен и решен создаются
  2. Добавить .then обработчик last_deferred
  3. .then обработчика обжигал и после того, как некоторые вещей он делает это решает deferred
  4. Временного deferred (таким образом спусковые .then на deferred)
  5. last_deferred переопределяется как deferred
  6. вернуться к 2.

Так что это своего рода асинхронного цикла (поскольку .animate является асинхронной операцией). На каждом шаге вы говорите «когда предыдущий deferred разрешен, сообщите ему, чтобы решить следующую».

+0

Да, это может решить мою проблему. Но не могли бы вы рассказать мне, как эта работа? Я пытаюсь прочитать API jQuery, но все же запутываю. – JamesYin

+0

@JamesYin Я обновил ответ. Надеюсь, теперь ясно, дайте мне знать, есть ли у вас больше вопросов. – freakish

+0

Ты спасаешь мою жизнь. Теперь я полностью понимаю, что может сделать «отложенный». Большое спасибо! – JamesYin

1

Проверьте это решение, используя функцию queue().

Эта функция ждет, пока анимация не завершится, а затем выполнит ее содержимое.

var anim = function(i) { 
 
    $('.test').eq(i).animate({'top':'20px'}, 350).queue(function() { 
 
    i++; 
 
    anim(i); 
 
    $(this).dequeue(); 
 
    }); 
 
} 
 
anim(0);
.test { 
 
    width:50px; 
 
    height:50px; 
 
    float: left; 
 
    margin-right:10px; 
 
    background-color:green; 
 
    position:relative; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<div class="test">test</div> 
 
<div class="test">test</div> 
 
<div class="test">test</div> 
 
<div class="test">test</div> 
 
<div class="test">test</div> 
 

0

Попробуйте с использованием .queue(), $.map(), .delay(); заменяя window.innerHeight на 100, px единицей для % единицей на .animate(); подставляя .animate для .css на complete обратного вызова

var ul = $("ul"); 
 
ul.queue("_fx", $.map(ul.find("li"), function(el, i) { 
 
    return function(next) { 
 
    return $(el).animate({ 
 
     top: "-" + window.innerHeight/10 + "px" 
 
    }, 100, function() {  
 
     $(this).delay(100).animate({ 
 
     top: window.innerHeight - $(this).height() * 1.5 + "px" 
 
     }, 100, next); 
 
    }) 
 
    }; 
 
})).dequeue("_fx");
body { 
 
    height: 200px; 
 
} 
 
ul li { 
 
    top: 150px; 
 
    position: relative; 
 
    width: 50px; 
 
    height: 50px; 
 
    background: red; 
 
    padding 8px; 
 
    display: inline-block; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> 
 
</script> 
 
<ul> 
 
    <li>a 
 
    </li> 
 
    <li>b 
 
    </li> 
 
    <li>c 
 
    </li> 
 
    <li>d 
 
    </li> 
 
    <li>e 
 
    </li> 
 
    <li>f 
 
    </li> 
 
    <li>g 
 
    </li> 
 
</ul>

Смежные вопросы