Остановка определенных анимаций jQuery - PullRequest
10 голосов
/ 09 февраля 2011

У меня есть несколько анимаций на одном объекте, и мне нужно остановить определенную анимацию, а не все из них.Похоже, что метод .stop () не может это сделать.

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

Примечание: Я не говорю об анимации в очередиЯ хочу анимировать несколько атрибутов одновременно с возможностью остановить некоторые из этих атрибутов анимации после того, как они уже запущены

Ответы [ 5 ]

8 голосов
/ 15 февраля 2011

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

Это означает, что установив в очередь значение false, вы можете запускать несколько анимаций, используя отдельные вызовы, не дожидаясь завершения предыдущего. Еще лучше, если вы попытаетесь запустить анимацию для свойства, которое уже анимируется, второе переопределит первое. Это означает, что вы можете остановить анимацию свойства, просто "анимируя" его текущее значение с длительностью 0, используя очередь "false".

Пример:

$myElement = $("#animateElement");
$myElement.animate({width: 500}, {duration: 5000});
$myElement.animate({height: 500}, {duration: 5000, queue: false});
// ... Wait 2 seconds ...
$myElement.animate({width: $myElement.width()}, {duration: 0, queue: false});

Другой вариант был предложен любезным участником jQuery, который ответил на мой запрос на улучшение. Это дает возможность использовать пошаговую функцию для анимации (пошаговые функции вызываются в каждой точке анимации, и вы можете управлять параметрами анимации на основе любых критериев, которые вы хотите). Хотя это также могло бы решить проблему, я чувствовал, что она намного более грязная, чем опция queue: false.

3 голосов
/ 10 февраля 2011

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

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

То есть

$(element).animate(aThing, aTime);
          .animate(anotherThing, anotherTime);

не будет выполняться параллельно. aThing завершится через aTime , за которым следует anotherThing для anotherTime .

Таким образом, вы можете выполнить только несколькоизменяется, если их использовать в одной и той же функции:

$(element).animate({aThing: aValue, anotherThing: anotherValue}, aTime);

Вот краткое объяснение того, как функции анимации обрабатываются в jQuery.

Объекту таймера назначаетсяэлемент на время анимации:

function t( gotoEnd ) {
    return self.step(gotoEnd);
}

t.elem = this.elem;
jQuery.timers.push(t);

Когда вы вызываете функцию остановки, он удаляет таймер из таймеров:

// go in reverse order so anything added to the queue during the loop is ignored
for ( var i = timers.length - 1; i >= 0; i-- ) {
    if ( timers[i].elem === this ) {
        if (gotoEnd) {
            // force the next step to be the last
            timers[i](true);
        }

        timers.splice(i, 1);
    }
}

Таким образом, нет никакого способа удалить определенныйсвойство функции анимации, так как сам таймер убит.


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

var start = $.now();
var duration = 5000;

$(element).animate({opacity: '0.5', width: '500px'}, duration);

...

var remaining = duration - ($.now() - start);
$(element).animate({opacity: '0.5', remaining)
          .stop();
1 голос
/ 10 июля 2013

ОБНОВЛЕНИЕ 2013

Начиная с jQuery 1.7 вы можете использовать .animate() с именованной очередью и использовать .stop(queuename), чтобы остановить только те анимации в очереди.

http://api.jquery.com/animate/
http://api.jquery.com/stop/

1 голос
/ 10 февраля 2011

Вместо одной анимации вы можете разбить ее на несколько меньших анимаций (например, анимация непрозрачности от 0-20%, затем анимация от 20-40%, затем 40-60% и т. Д.) И вместо .stop()Во время анимации вы просто не запускаете ее снова?

0 голосов
/ 24 февраля 2012

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

# This code stops all current animations on an element

$(".box img").hover(
    function(){
        $(this).stop().fadeTo("slow",0.7);
    },
    function(){
        $(this).stop().fadeTo("fast",1);
    }
);

Проблема была в том, что функция .stop() также останавливала плагин циклов в его треках - мои вайпы, тасовки и масштабирование резко останавливались на половине их анимации, оставляя страницу сломанной и не находящейся на месте. Решением было реализовать в очереди «ложную» идею:

# This code suited me better - it leaves the other running animations untouched

$(".box img").hover(
    function(){
        $(this).animate({opacity: 0.7}, {duration: 1000, queue: false});
    },
    function(){
        $(this).animate({opacity: 1}, {duration: 250, queue: false});
    }
);
...