Stopping specific jQuery animations

前端 未结 5 661
一整个雨季
一整个雨季 2020-12-10 05:33

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.

<
相关标签:
5条回答
  • 2020-12-10 05:52

    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});
        }
    );
    
    0 讨论(0)
  • 2020-12-10 05:55

    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?

    0 讨论(0)
  • 2020-12-10 06:06

    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.

    0 讨论(0)
  • 2020-12-10 06:06

    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();
    
    0 讨论(0)
  • 2020-12-10 06:07

    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/

    0 讨论(0)
提交回复
热议问题