Подтвердить что ты не робот

Как я могу создать цепочку или поставить в очередь пользовательские функции с помощью JQuery?

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

Я пытаюсь автоматизировать несколько событий в последовательности, чтобы выглядеть так, как пользователь нажимал на разные кнопки или ссылки.

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

Помогает ли jQuery "queue"? Я не мог понять документацию для очереди.

Пример: JQuery:

 function One() {
        $('div#animateTest1').animate({ left: '+=200' }, 2000);
    }
    function Two() {
        $('div#animateTest2').animate({ width: '+=200' }, 2000);
    }

// Call these functions sequentially so that the animations
// in One() run b/f the animations in Two()
    One();
    Two();

HTML:

    <div id="animatetest" style="width:50px;height:50px;background-color:Aqua;position:absolute;"></div>
    <div id="animatetest2" style="width:50px;height:50px;background-color:red;position:absolute;top:100px;"></div>

Спасибо.

EDIT: Я попробовал это с timers, но я подумал, что есть лучший способ сделать это.

ИЗМЕНИТЬ № 2:

Позвольте мне быть более конкретным. У меня есть несколько функций, связанных с событиями кликов и зависаний на разных элементах страницы. Обычно эти функции не имеют ничего общего друг с другом (они не ссылаются друг на друга). Я хотел бы моделировать пользователя, проходящего через эти события, без изменения кода моих существующих функций.

4b9b3361

Ответ 1

Код очереди jQuery не так хорошо документирован, как может быть, но основная идея такова:

$("#some_element").queue("namedQueue", function() {
  console.log("First");
  var self = this;
  setTimeout(function() {
    $(self).dequeue("namedQueue");
  }, 1000);
});

$("#some_element").queue("namedQueue", function() {
  console.log("Second");
  var self = this;
  setTimeout(function() {
    $(self).dequeue("namedQueue");
  }, 1000);
});

$("#some_element").queue("namedQueue", function() {
  console.log("Third");
});

$("#some_element").dequeue("namedQueue");

Если вы запустите этот код, вы увидите "First" в консоли, паузу в 1s, см. "Второе" в консоли, другую паузу в 1 секунду и, наконец, увидите "Третий" в консоли.

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

Анимации в jQuery все запускаются в очереди с именем fx. Когда вы анималируете элемент, он автоматически добавляет новую анимацию в очередь и вызывает dequeue, если анимация не выполняется. Вы можете вставить свои собственные обратные вызовы в очередь fx, если хотите; вам просто нужно будет вызвать dequeue вручную в конце (как и при использовании любой другой очереди).

Ответ 2

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

Затем я бы добавил вызов функции, который перебирает массив и вызывает каждую функцию в событии через jQuery.

Возможно, вы создали очень простой плагин для jQuery, который мог бы обрабатывать и его внутренне.

Ответ 3

Предполагая, что вы хотите сохранить One и Two в качестве отдельных функций, вы можете сделать что-то вроде этого:

function One(callback) {
    $('div#animateTest1').animate({ left: '+=200' }, 2000, 
        function(e) { callback(); });
}
function Two() {
    $('div#animateTest2').animate({ width: '+=200' }, 2000);
}

// Call these functions sequentially so that the animations
// in One() run b/f the animations in Two()
    One(Two);

Ответ 4

Я бы запустил вторую функцию обратного вызова:

$('div#animateTest1').animate({ left: '+=200' }, 2000, function(){
    two();
});

который будет запускать два(), когда заканчивается первая анимация, если у вас больше анимаций в тайм-очереди для таких случаев, я использую плагин jquery timer вместо setTimeout(), что очень удобно в некоторых случаях.

Ответ 5

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

Чтобы обернуть функцию, вам нужно знать функцию apply. Функция apply принимает объект для области видимости и массив аргументов. Таким образом вам не нужно ничего знать о функциях, которые вы обертываете.

Ответ 6

Как насчет чего-то подобного?

var f1 = function() {return $(SELECTOR1).animate({ 'prop': 'value' }, 1000)};
var f2 = function() {return $(SELECTOR2).animate({ 'prop': 'value' }, 1000)};
var f3 = function() {return $(SELECTOR3).animate({ 'prop': 'value' }, 1000)};

$.when(f1).then(f2).then(f3);

Ответ 7

Более безопасный и 100% рабочий способ - использовать переменную и if-ветки. В приведенном ниже примере мы выполняем 4 задания, которые занимают 1 секунду, после задания мы хотим запустить функцию f2.

<html><body>
<div id="a" class="a" />
 <script type="text/javascript">
var jobs = 0;
function f1() {
job(); 
job();
job();
job();    
};

function f2() {
    if(jobs >3)
        l("f2");
};

<!------------------------- ->
function job() {
    setTimeout(function() {
        l("j");
        jobs+=1;
        f2();
    }, 1000);
}
function l(a) {
    document.getElementById('a').innerHTML+=a+"<br />";
};
f1();


</script></body></html>

Ответ 8

Действительно простое исправление.

function One() {
        $('div#animateTest1').animate({ left: '+=200' }, 2000, Two);
    }
    function Two() {
        $('div#animateTest2').animate({ width: '+=200' }, 2000);
    }

// Call these functions sequentially so that the animations
// in One() run b/f the animations in Two()
    One();
//We no longer need to call Two, as it will be called when 1 is completed.
    //Two();

Ответ 9

Что касается интервала анимации, который уже определен в 2000 мс, вы можете выполнить второй вызов с задержкой в ​​2000 мсек:

One();
SetTimeout(function(){
  Two();
}, 2000);

Ответ 10

Следующее будет работать и не будет ошибкой, если обратный вызов равен null:

function One(callback)
{
    $('div#animateTest1').animate({ left: '+=200' }, 2000, 
       function()
       {
            if(callback != null)
            {
                 callback();
            }
       }
    );
}
function Two()
{
    $('div#animateTest2').animate({ width: '+=200' }, 2000);
}

var callback = function(){ Two(); };
One(callback);

Ответ 11

@TrippRitter должен присоединить .call к обратному вызову

One = function(callback){
    $('div#animateTest1').animate({ left: '+=200' }, 2000, function(){
        if(typeof callback == 'function'){
            callback.call(this);
        }
    });
}

Two = function(){
    $('div#animateTest2').animate({ width: '+=200' }, 2000);
}

One(function(){ 
    Two();
});

но это то же самое, что и выполнение следующих

$('div#animateTest1')
    .animate({ left: '+=200' }, 2000, 
    function(){
       Two();
    });

Two = function(){
    $('div#animateTest2').animate({ width: '+=200' }, 2000);
}

Ответ 12

$('div#animateTest1').animate({left: '+=200'},2000, 
function(){
   $('div#animateTest2').animate({ width: '+=200' }, 2000);
}
);

Ответ 13

Копирование и вставка............ 7/9/2013

<!doctype html>
<html lang="en">
    enter code here<head>
  <meta charset="utf-8">
  <title>jQuery.queue demo</title>
  <style>
  div { margin:3px; width:40px; height:40px;
        position:absolute; left:0px; top:30px;
        background:green; display:none; }
  div.newcolor { background:blue; }
    </style>
  <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
</head>
<body>

  <button id="start">Start</button>
  <button id="stop">Stop</button>
  <div></div>
<script>
   $("#start").click(function () {
      $("div").show("slow");
      $("div").animate({left:'+=200'},5000);
      jQuery.queue( $("div")[0], "fx", function () {
        $(this).addClass("newcolor");
        jQuery.dequeue( this );
      });
      $("div").animate({left:'-=200'},1500);
      jQuery.queue( $("div")[0], "fx", function () {
        $(this).removeClass("newcolor");
        jQuery.dequeue( this );
      });
      $("div").slideUp();
    });
    $("#stop").click(function () {
      jQuery.queue( $("div")[0], "fx", [] );
      $("div").stop();
    });
</script>

</body>
</html>

Ответ 14

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

Я создал плагин для таких ситуаций, как ваш, который позволяет выполнять функции очередей (при необходимости приостанавливать и возобновлять).

demo: https://jessengatai.github.io/okaynowthis.js/

Решение вашей проблемы с использованием okaynowthis.js будет выглядеть так:

$('window').load(function(){

    // keyframe 1
    $('body').okaynowthis('keyframe',0,function(){
        $('div#animateTest1').animate({ left: '+=200' }, 2000);
        // + anything else you want to do

    // keyframe 2 (with 2 seconds delay from keyframe 1)
    }).okaynowthis('keyframe',2000,function(){
        $('div#animateTest2').animate({ left: '+=200' }, 2000);
        // + anything else you want to do

    });

});

Ответ 15

Вместо создания функции простой способ:

$('#main').animate({ "top": "0px"}, 3000, function()
   {    $('#navigation').animate({ "left": "100px"},  3000, function() 
        {
            alert("Call after first and second animation is completed.");
        })
    }
);

Итак, Jquery по умолчанию предоставляет очередь, которая выполняет функцию один за другим.