我期待为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()
。有人可以帮帮我吗?
答案 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
}
}
}
);