自定义jQuery Easing功能,可访问价值

时间:2013-12-17 16:04:54

标签: javascript jquery html css animation

我期待为jQuery动画创建一个自定义缓动函数,我找到了一个很好的例子来扩展jQuery中的缓动。看看:Looking for jQuery easing functions without using a plugin

但这种方法不适合我的情况 我有一个函数需要处理该值不仅基于时间而且基于start和value。例如:

$("selector").animate({ "height": "1400px" }, 1000);

我找到的方法使用一个接收5个参数的函数,所有参数都与时间有关。

但我还需要更多。我还需要起始值(DOM在动画之前具有的值)和结束值(DOM在动画之后的值)。

在我的示例中,值指的是高度(原始高度和1400px)。

我知道你在想我为什么需要价值信息,所以我已经写了自定义函数:

var offset = 400;

function myEasing(millisecondsSince, totalMilliseconds, startValue, endValue) {
    var t = millisecondsSince / totalMilliseconds;

    if (startValue == 0) startValue = 0.000001;

    if (t <= 0.5) {
        var m = (Math.log(endValue - offset) - Math.log(startValue))
                / (0.5 * Math.LN10);
        var n = Math.log(startValue) / Math.LN10;
        return Math.pow(10, m * t + n); // y = 10 ^ (mx + n)
    }

    var m = 2 * Math.pow(offset, 0.2);
    return Math.pow(m * t - m, 5) + endValue; // y = (mx - m) ^ 5 + endValue
}

但我的问题是如何将此功能合并到jQuery.animate()。有人可以帮帮我吗?

1 个答案:

答案 0 :(得分:0)

这是我在SO上的第一次击键,我既没有账号,也没有个人资料,也没有任何声誉, 但是我正在开发一个jQuery插件,它允许使用额外的参数来缓和函数。

为了回答你的问题,我做了以下假设(如果我错了请告诉我,我会更新我的答案): 1.你使用jQuery&gt; = 1.8(他们在那里修改了他们的动画例程)。 2.您的$(“选择器”)可能包含多个元素。 3.动画属性的startValue(此处为“height”)可能因元素而异。 4.只要有办法合并你的功能,你就不会坚持使用自定义缓和。

我看到两个解决方案。为了解释我的工作和原因,这里是jQuery核心的片段:

// jQuery creates for each animated property of each animated element a Tween object.
// .run() of its prototype is called at each step of the animation.
Tween.prototype = {
    run: function( percent ) {
        // percent = actual state of the animation, a number between 0 (start) and 1 (end)
        // percent is identic with your var t, you dont need to recalculate it
        // this refers to the whole Tween object you are actual in
        var eased,
            hooks = Tween.propHooks[ this.prop ];

        if ( this.options.duration ) {
            // here the choosen easing function is called. It must be declared in $.easing under its name
            // before animation is running, otherwise an error is thrown. But before starting you don't know
            // the startValue, so your function can't reference to it
            this.pos = eased = jQuery.easing[ this.easing ](
                // here the  five arguments are passed in. Every easing function in $.easing, even custom ones,
                // have this signature (x, t, b, c, d), they may use the arguments or not. Changing this signature
                // breaks any other code that relies on easings
            percent, this.options.duration * percent, 0, 1, this.options.duration
                // But being shameless, you may extend the signature with the additional arguments you need
        /*  percent, this.options.duration * percent, 0, 1, this.options.duration, this.start, this.end  */
                // now there are seven arguments and you can restructure your function to use the three you need
            );
        } else {
            this.pos = eased = percent;
        } // at this point the easing result is stored in this.pos. When using 'linear' its identic with percent
          // (and with your var t) so we can use this.pos in the second solution

        // after calculation this.now holds the actual value of the animated property. When you havn't done
        // the modification above, you can't use your function for easing and this.now hasn't the value you want
        this.now = ( this.end - this.start ) * eased + this.start;

        if ( this.options.step ) {
            // if you have defined a function in options.step it gets called now. Two arguments are passed in:
            // the actual value, the whole Tween object. The latter holds all values you need
            // to recalculate this.now with your function
            this.options.step.call( this.elem, this.now, this );
        }

        if ( hooks && hooks.set ) {
            hooks.set( this );
        } else {
            Tween.propHooks._default.set( this );
        }
        return this;
    }
};

解决方案1:您已完成上述jQuery的修改。然后:

var offset = 400;
$.easing["myFunction"] = function(x, t, b, c, d, startValue, endValue) {
    /* replace your var t with x; args t b c d not needed; your done; */
};
$("selector").animate({ "height": "1400px" }, 1000, "myFunction");

解决方案2:你不会在jQuery中乱搞。然后:

您可以将选项对象传递给.animate(),而不是持续时间,缓动和完成的离散参数。 有关详细信息,请参阅http://api.jquery.com/animate/。 使用specialEasing,您可以单独定义每个属性的缓动。这样你就可以保留所有可能性 在同一个调用中为“height”设置其他属性的动画,而不会使用“myFunction”影响它们。

$("selector").animate(
    { height: "1400px" , otherProp: "otherVal"}, {
        duration: 1000, // your duration
        specialEasing: {
            height: "linear" // easing happens before step, linear won't confuse your calculations
            otherProp: "anyEasingYouWant"
        },
        step: function(now, tween) {
            // you are restricted to the two arguments jQuery passes to this function. But the Tween object
            // holds all values you need to modify tween.now (= the animation output value) as you like
            // if you animate more than one property and want apply your calcs only to one, do exclusions here.
            // it's needed cause this function is executed once for each property of each element at each step.
            if (tween.prop !== "height") return;
            var ofs = 400, // your offset
                stv = tween.start || 0.000001, // your startValue
                env = tween.end, // your endValue
                dif = env - stv, // difference between start and end to recalculate the actual value
                pos = tween.pos, // your var t
                m, n;
            if (pos <= 0.5) {
                m = (Math.log(env - ofs) - Math.log(stv)) / (0.5 * Math.LN10);
                n = Math.log(stv) / Math.LN10;
                tween.now = dif * Math.pow(10, m * pos + n) + stv; // y = 10 ^ (mx + n)
            } else {
                m = 2 * Math.pow(offset, 0.2);
                tween.now = dif * (Math.pow(m * pos - m, 5) + env) + stv; // y = (mx - m) ^ 5 + endValue
            }
        }
    }
);