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

Как я могу анимировать несколько элементов последовательно с помощью jQuery?

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

$(".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");
});
4b9b3361

Ответ 1

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

$(".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");        
            });
        });
    });
});

Ответ 2

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

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

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

Пример script

  $("#1").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
  $("#2").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
  $("#3").animate({marginTop: "100px"}, {duration: 100, queue: "global"});

Ответ 3

Я знаю, что это старый вопрос, но он должен быть обновлен с ответом на новые версии 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");        
});

Ответ 4

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

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

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

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

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

Ответ 5

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

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

Вот скрипка

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

Ответ 6

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

Вы можете задействовать встроенную анимацию анимации 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/

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

  • Вызов $.globalQueue.queue() просто вызывает вызов вашей анимации тегов, но он помещает его в тег body.

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

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

  • Для удобства метод 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/

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

Ответ 7

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

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

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

Ответ 8

Это уже ответили хорошо (я думаю, что ответ 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: FYI jQuery "медленная" скорость также равна 600 миллисекунд. поэтому, если вы хотите использовать "медленные" в своей анимации, просто используйте эти значения в каждом последующем вызове функции задержки - 600, 1200, 1800

Ответ 9

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

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

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

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

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

function startShowing(){
      $('.pattern-board.transparent:first').animate(
        { opacity: 1}, 
        1000,
        function(){
          $(this).removeClass('transparent');
          startShowing();
        }
      );
    }

Ответ 10

Используйте параметр 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" });
});