jQuery动画stop()触发缓出

时间:2012-11-18 17:27:59

标签: jquery jquery-animate

这是一个普遍的问题。

如果我在元素#elm上有一个jQuery动画,我可以使用$('#elm').stop()

来阻止它

通常动画会有一个很好的easeIn,easeOut(就像默认的'swing')。打电话'停止()'立即停止,当场,看起来有点笨重。调用$('#elm').stop(true,true)使其立即完成动画,一直到终点。

是否有通用方法告诉元素“更改正在运行的动画,以便它'很快'和'附近'停止,但使用首先定义的easeOut”?

好奇, * -pike

1 个答案:

答案 0 :(得分:5)

派克,

我不知道做一个“gentle_stop”的完全通用的方法 - 一个可以在任何动画上运行的方式,无论它是如何被初始化的。

下面的代码定义了函数gentleStoppable(),它实际上是jQuery自己的.animate( properties, options )方法的4参数版本。额外的两个参数指定了“平缓 - 停止”阶段。

这是功能:

function gentleStoppable($jQ, animProps, animOptions, stopProps, stopOptions) {
    var namespace = 'gentleStop';
    var dfltStopOptions = {
        duration: 'slow',//override with stopOptions.duration .
        easing: 'easeOutCubic',//override with stopOptions.easing . (See also the safety check applied after extending dfltStopOptions below).
        queue: namespace
    };
    animProps = animProps || {};
    animOptions = animOptions || {};
    stopProps = stopProps || {};
    stopOptions = stopOptions || {};
    $jQ.each(function(i, elem) {
        var $elem = $(elem);
        function killCustomEvent() { $elem.off(namespace); }
        var C = $.Callbacks('once').add(killCustomEvent);
        if(animOptions.complete) {
            C.add(animOptions.complete);
        }
        animOptions.complete = C.fire;
        stopProps = $.extend({}, animProps, stopProps);
        stopOptions = $.extend({}, animOptions, dfltStopOptions, stopOptions);
        stopOptions.easing = ($.easing && $.easing[stopOptions.easing] ) ? stopOptions.easing : 'swing';//just in case what's specifified is unavailable.
        $elem.on(namespace, function() {//custom event
            killCustomEvent();
            C.remove(killCustomEvent);//prevent killCustomEvent being called twice.
            $elem.stop(true,false).animate(stopProps, stopOptions).dequeue(namespace);
        }).animate(animProps, animOptions);
    });
}

启动一个gentleStoppable动画,如下所示:

var animProps = {
    left: '300px'
};
var animOptions = {
    duration: 2000,
    complete: function() {
        console.log('complete');
    }
};
var stopProps = {
    left: '+=15px'
};
var stopOptions = {
    duration: 500,
};
gentleStoppable($e1, animProps, animOptions, stopProps, stopOptions);

然后轻轻地停下来:

$("#elem").trigger('gentleStop');

Demo

目前,功能并不完美,我只通过有限的测试。以下是已知的问题/改进:

  • 方向:xxx:+=15px形式的stopProps属性将在softstop阶段无条件地添加15px,即使它处于错误的方向。例如,如果相应的animProps属性为xxx:30px,则+=15px将假定从下方接近目标值30px。类似地,值-=15px将假设从上方接近相应的目标值。对gentleStoppable()的改进将自动调整每个stopProps属性,以允许从低于或高于上方接近其相应的animProps属性。

  • Overshoot:xxx:+=15px形式的stopProps属性将无条件地在reststop阶段添加15px,即使+ 15px使得温和动画超出相应animProps属性中指定的值。如果动画在其自然结束附近停止,则会发生这种情况。对gentleStoppable()的改进会自动阻止每个stopProps的属性导致其超出相应的animProps属性。

  • 自动计算:一个毫无疑问的改进是gentleStoppable()根据animProp计算自身的stopProps值。这将使函数通用,更易于使用,并且正确编写将有效地修复方向和过冲问题。

  • 稍微考虑一下,代码可以重构为jQuery插件,这样会更方便,因为它允许方法链接并避免相当笨拙的.trigger(...)执行轻柔停止。

如果这有用,请使用它。