Stopping specific jQuery animations

强颜欢笑 提交于 2019-12-17 19:23:09

问题


I have multiple animations on a single object, and I need to stop a specific animation rather than all of them. It doesn't look like the .stop() method can do this.

For instance, when animating opacity and width simultaneously, I may need to cancel the opacity animation while still completing the width animation. It would seem that this is not possible, but I am hoping that someone knows a trick or an API call that I'm missing.

Note: I'm not talking about queued animations, I'm looking to animate multiple attributes at the same time with the ability to stop some of those attribute animations after they have already started


回答1:


I hate to be a guy who answers his own question (thanks so much for the detailed responses and putting brain power into it!) but I have found a direct answer. Apparently there is a parameter for the .animate() method called "queue" which defaults to true but you can set to false in order to have your animation take place immediately.

This means that by setting queue to false you can run multiple animations using separate calls without having to wait for the previous one to finish. Better yet, if you try to run an animation for a property which is already being animated, the second will override the first. This means you can stop a property's animation by simply "animating" it to its current value with a duration of 0, using queue "false".

An Example:

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

Another option was suggested by a gracious jQuery contributor who responded to my enhancement request. This takes advantage of the ability to use a step function on an animation (step functions are called at every point in the animation, and you can manipulate the animation parameters based on whatever criteria you want). Although this also could have solved the issue, I felt it was far more dirty than the "queue: false" option.




回答2:


After thinking about this a little harder about this, I realized that what you're trying to do isn't easy doable because of the way animations are handled in jQuery.

Since animations are managed by a queue, it not possible to run concurrent animations on the same element without them being in the same function.

That is to say,

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

isn't going to run in parallel. aThing will finish in aTime, followed by anotherThing lasting for anotherTime.

Thus, you can only accomplish multiple changes by having them in the same function:

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

Here's a quick explanation of the anatomy of how animation functions are handled within jQuery.

A timer object is assigned to the element for the duration of the animation:

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

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

When you call the stop function, it removes the timer from timers:

// 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);
    }
}

So, there is no way to remove a specific property of an animation function since the timer itself is killed.


The only way I could think of accomplishing this would be to keep track of the start time and duration, re-enqueuing the animation and stopping the current one.

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



回答3:


Instead of one animation, can you break it up into several smaller animations (i.e. animate opacity from 0-20%, then animate from 20-40%, then 40-60%, etc) and instead of .stop()-ing the animation, you just dont start it up again?




回答4:


UPDATE 2013

As of jQuery 1.7 you can use .animate() with a named queue, and use .stop(queuename) to stop only those animations in the queue.

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




回答5:


I'm using jQuery cycle plugin to animate a dozen slide shows on the same page using various different animation types (wipes, shuffles, zooms, etc). I then had my own tiny script to fade the images slightly as you hovered over each slideshow:

# 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);
    }
);

The problem was the .stop() function was also stopping the cycle plugin in it tracks - my wipes, shuffles and zooms were stopping abruptly half way through their animation leaving the page fractured and out of position. The solution was to implement your queue "false" idea:

# 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});
    }
);


来源:https://stackoverflow.com/questions/4949784/stopping-specific-jquery-animations

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!