Как я могу анимировать несколько элементов последовательно, используя jQuery? - PullRequest
32 голосов
/ 02 августа 2009

Я думал, что это будет просто, но я все еще не могу заставить его работать. Нажав одну кнопку, я хочу, чтобы происходило несколько анимаций - одна за другой - но теперь все анимации происходят одновременно. Вот мой код - может кто-нибудь сказать мне, где я иду не так?

$(".button").click(function(){
  $("#header").animate({top: "-50"}, "slow")
  $("#something").animate({height: "hide"}, "slow")
  $("ul#menu").animate({top: "20", left: "0"}, "slow")
  $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow");
});

Ответы [ 10 ]

29 голосов
/ 02 августа 2009

Очередь работает только если у вас анимация одного и того же элемента. Господь знает, почему за это проголосовали, но это не сработает.

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

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

Пример сценария

  $("#1").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
  $("#2").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
  $("#3").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
26 голосов
/ 06 июля 2012

Я знаю, что это старый вопрос, но его следует обновить, добавив ответ для более новых версий jQuery (1.5 и выше):

Используя функцию $.when, вы можете написать этот помощник:

function queue(start) {
    var rest = [].splice.call(arguments, 1),
        promise = $.Deferred();

    if (start) {
        $.when(start()).then(function () {
            queue.apply(window, rest);
        });
    } else {
        promise.resolve();
    }
    return promise;
}

Тогда вы можете назвать это так:

queue(function () {
    return $("#header").animate({top: "-50"}, "slow");
}, function () {
    return $("#something").animate({height: "hide"}, "slow");
}, function () {
    return $("ul#menu").animate({top: "20", left: "0"}, "slow");
}, function () {
    return $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow");        
});
24 голосов
/ 02 августа 2009

Вы можете сделать несколько обратных вызовов.

$(".button").click(function(){
    $("#header").animate({top: "-50"}, "slow", function() {
        $("#something").animate({height: "hide"}, "slow", function() {
            $("ul#menu").animate({top: "20", left: "0"}, "slow", function() {
                $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow");        
            });
        });
    });
});
6 голосов
/ 08 января 2013

Небольшое улучшение ответа @ schmunk заключается в использовании простой очереди объекта jQuery для избежания конфликта с другими не связанными анимациями:

$({})
    .queue(function (next) {
        elm1.fadeOut('fast', next);
    })
    .queue(function (next) {
        elm2.fadeIn('fast', next);
    })
    // ...

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

Работа с простыми объектами

В настоящее время поддерживаются только операции над простыми объектами JavaScript, заключенными в jQuery. являются: .data (), prop (),. bind (), .unbind (), .trigger () и .triggerHandler ().

2 голосов
/ 19 октября 2014

Последовательная анимация нескольких тегов

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

// Convenience object to ease global animation queueing
$.globalQueue = {
    queue: function(anim) {
        $('body')
        .queue(function(dequeue) {
            anim()
            .queue(function(innerDequeue) {
                dequeue();
                innerDequeue();
            });
        });

        return this;
    }
};

// Animation that coordinates multiple tags
$(".button").click(function() {
    $.globalQueue
    .queue(function() {
        return $("#header").animate({top: "-50"}, "slow");
    }).queue(function() {
      return $("#something").animate({height: "hide"}, "slow");
    }).queue(function() {
        return $("ul#menu").animate({top: "20", left: "0"}, "slow");
    }).queue(function() {
        return $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow");
    });
});

http://jsfiddle.net/b9chris/wjpL31o0/

Итак, вот почему это работает, и что он делает:

  1. Вызов $.globalQueue.queue() просто ставит в очередь вызов анимации вашего тега, но ставит его в очередь в теге body.

  2. Когда jQuery попадает в анимацию вашего тега в очереди тела, анимация вашего тега запускается в очереди для вашего тега - но, как работает инфраструктура анимации jQuery, любой пользовательский обратный вызов анимации вызывает очередь анимации тега (тело в этом случае) для остановки, пока пользовательская анимация не вызовет переданную функцию dequeue(). Таким образом, хотя очереди для вашего анимированного тега и тела разделены, очередь тега тела теперь ожидает вызова dequeue(). http://api.jquery.com/queue/#queue-queueName-callback

  3. Мы просто делаем последний элемент очереди в очереди тега вызовом для продолжения глобальной очереди, вызывая его функцию dequeue() - это то, что связывает очереди вместе.

  4. Для удобства метод globalQueue.queue возвращает ссылку this для легкого сцепления.

setInterval

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

Вы можете заменить вызов на setInterval следующим образом:

setInterval(doAthing, 8000);

С этим:

/**
 * Alternative to window.setInterval(), that plays nicely with modern animation and CPU suspends
 */
$.setInterval = function (fn, interval) {
    var body = $('body');
    var queueInterval = function () {
        body
        .delay(interval)
        .queue(function(dequeue) {
            fn();
            queueInterval();
            dequeue();  // Required for the jQuery animation queue to work (tells it to continue animating)
        });
    };
    queueInterval();
};

$.setInterval(doAthing, 8000);

http://jsfiddle.net/b9chris/h156wgg6/

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

2 голосов
/ 26 июня 2012

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

Здесь представлен список выбранных элементов, но это может быть список более сложных объектов, содержащих разные параметры анимации для каждой анимации.

Вот скрипка

$(document).ready(function () {
    animate([$('#one'), $('#two'), $('#three')], finished);
});

function finished() {
    console.log('Finished');
}

function animate(list, callback) {
    if (list.length === 0) {
        callback();
        return;
    }
    $el = list.shift();
    $el.animate({left: '+=200'}, 1000, function () {
        animate(list, callback);
    });
}
1 голос
/ 15 августа 2011

На этот вопрос уже получен хороший ответ (я думаю, что ответ jammus - лучший), но я подумал, что предоставлю другой вариант, основанный на том, как я делаю это на моем веб-сайте, используя функцию delay() ...

  $(".button").click(function(){
     $("#header").animate({top: "-50"}, 1000)
     $("#something").delay(1000).animate({height: "hide"}, 1000)
     $("ul#menu").delay(2000).animate({top: "20", left: "0"}, 1000)
     $(".trigger").delay(3000).animate({height: "show", top: "110", left: "0"}, "slow");
});

(замените 1000 на желаемую скорость анимации. Идея заключается в том, что ваша функция задержки задерживает на эту величину и накапливает задержку в анимации каждого элемента, поэтому, если бы ваши анимации были каждые 500 миллисекунд, ваши значения задержки были бы 500, 1000, 1500)

edit: 'медленная' скорость FQI jquery также составляет 600 миллисекунд. поэтому, если вы хотите использовать «медленные» кадры в своих анимациях, просто используйте эти значения при каждом последующем вызове функции задержки - 600, 1200, 1800

1 голос
/ 30 апреля 2010

Вы также можете поместить свои эффекты в одну и ту же очередь, то есть очередь элемента BODY.

$('.images IMG').ready(
   function(){
        $('BODY').queue(
            function(){
                $('.images').fadeTo('normal',1,function(){$('BODY').dequeue()});
            }
        );
    }
);

Убедитесь, что вы вызываете dequeue () в последнем обратном вызове эффекта.

0 голосов
/ 15 мая 2019

Я думал о решении для возврата.

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

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

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

Это функция, которую я сделал, чтобы опробовать ее

function startShowing(){
      $('.pattern-board.transparent:first').animate(
        { opacity: 1}, 
        1000,
        function(){
          $(this).removeClass('transparent');
          startShowing();
        }
      );
    }
0 голосов
/ 02 августа 2009

Используйте параметр queue:

$(".button").click(function(){
  $("#header").animate({top: "-50"}, { queue: true, duration: "slow" })
  $("#something").animate({height: "hide"}, { queue: true, duration: "slow" })
  $("ul#menu").animate({top: "20", left: "0"}, { queue: true, duration: "slow" })
  $(".trigger").animate({height: "show", top: "110", left: "0"}, { queue: true, duration: "slow" });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...