1

这是一个有点笼统的问题。

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

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

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

好奇,*-派克

4

1 回答 1

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

演示

就目前而言,该功能并不完美,我只对其进行了有限的测试。以下是已知问题/改进:

  • 方向:表单的一个 stopProps 属性xxx:+=15px会在柔和停止阶段无条件地增加 15px,即使它的方向是错误的。例如,如果相应的 animProps 属性是,xxx:30px+=15px假定目标值30px是从下方接近的。同样, 的值-=15px将假定从上方接近相应的目标值。对gentleStoppable() 的改进将自动调整每个stopProps 属性,以允许从下方或上方接近其对应的animProps 属性。

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

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

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

如果这有任何用处,那么请使用它。

于 2012-11-20T03:08:13.797 回答