我创建了一个简单的函数,它根据当前滚动位置设置动画值。
function scrollTransition(startValue, endValue, initScroll, distance, scrollTop) {
var
min = Math.min,
max = Math.max,
sum;
if(startValue > endValue) {
sum = min(max((endValue - startValue) / distance * (scrollTop - initScroll) + startValue, endValue), startValue);
} else {
sum = min(max((endValue - startValue) / distance * (scrollTop - initScroll) + startValue, startValue), endValue);
}
return sum;
}
您所要做的就是设置一个起始值和结束值,初始滚动位置,转换开始时和距离(以px为单位)。因此,如果“initScroll”为500且距离为200,则转换结束于700px(scrollTop)。 “问题”是,它只是一个线性动画。我想要做的是在函数中添加第五个参数(“缓动”),就像在jQuery .animation()函数中一样。
这些是我正在谈论的缓动函数(https://github.com/danro/jquery-easing/blob/master/jquery.easing.js),但我不确定,如何将它们添加到此函数中,所以我可以使用像
这样的东西// in window scroll function
$el.css({
"margin-top" : scrollTransition(-300, 500, 500, 1000, "easeOutBack")
});
这样的事情是可能的,还是我必须坚持线性过渡?
提前感谢您的帮助和时间。
答案 0 :(得分:10)
嗯,我花了一些时间,但我想我明白了。因为你制作了自己的定制'功能,它有点难以完成。
为了解释我所做的一切,让我们从线性公式的绝对基础开始。
f(x)=x
g(x)=sin(x)
视为我们的缓动函数(这对应于缓动方法easeInSine
)让我们在二维图中考虑这些函数:
如您所见,我现在已经绘制了两个不同的功能。如果我们将这些函数可视化为JavaScript中的函数,那么它们是我们可以独立调用的两个独立函数。例如:
function linear(x)
{
return x;
}
function sin(x)
{
return Math.sin(x);
}
现在我们可以将这两个函数用作scrollTransition,但这不是我们想要的。
您问了具体的问题:如何将非线性函数添加到我的自定义线性函数中?
因此,让我们考虑一下我们的两个功能的可能性:
让我们想象出第一点:
灰线表示原始功能,蓝线表示添加的功能。
对于第二点,我们会得到:
同样,灰色线表示原始功能,蓝色线表示添加在一起的功能。 (嗯......在这种情况下:' 相互减去')
让我们考虑一下我们所知道的一切:
就像图表一样,我们可以添加和减去这些值以将函数组合在一起。
为了完成你的功能,我在你的函数中添加了两个参数:
easingEffect
应该是您要从自定义函数添加(或减去)的非线性缓动效果的名称plus
可以使用值-1
,0
和1
,这将决定如何处理非线性效果:
-1
非线性函数将从您的自定义线性函数0
不会使用非线性函数1
非线性函数将添加到您的自定义线性函数这方面的一个例子是:
$(".element").css({
"opacity": 1-scrollTransition(0, 1, 0, 400, scrollTop, "easeInSine", 1),
"left": scrollTransition(0, 200, 0, 300, scrollTop, "easeOutBounce", 1)
});
然后我在你的功能中做了什么基本上归结为以下几点:
sum += plus*easingEffect(null, scrollTop, startValue, endValue, distance);
缓和效果取决于您自己提供的easing js。
不幸的是,我最终做了很多手动工作,因为对于你的自定义函数,我们需要缓动函数来返回值,而不必调用jQuery.animate()
函数。但是你不必再担心了:我已经完成了所有工作,所以现在你可以坐下来玩设置,看看会发生什么。
您可以在此处找到(完全可实施的)解决方案:the code at jsFiddle。
你可以做一些很酷的事情,比如this。
请注意以下事项:
对于opacity
,将两个值加在一起非常危险,因为如果您尝试传递的参数大于1
,则CSS属性会出错。因此,我会做以下事情:
"opacity": 1-scrollTransition(0, 1, 0, 400, scrollTop, "easeInSine", 1),
所以我基本上颠倒了函数(我让函数'从0到1而不是从1到0工作)然后我做1-'the function'
以确保值永远不会超过请注意,这应该与减去或添加非线性函数一致。
此外,如果您在javascript中向下滚动,您将看到所有函数和巨大的switch语句:您必须将所有这些添加到最终的javascript文件中。
所以我建议您只需将整个javascript部分复制到您自己的项目中。
此外,jsFiddle应该是不言自明的。
祝你好运,我希望我回答你的问题! demrks
执行了以下操作:
sum = easeOutBounce(null, sum, startValue, endValue, distance);
要获得更多关于将参数sum
添加到缓动函数的直觉,请考虑以下图表:
蓝线表示您的功能结果。
所以你基本上做的是称为缓动函数的linear transformation
或缓动函数linear mapping
。您可以阅读有关此here的更多信息。
但它基本上归结为你正在改变形式'通过以下属性的缓动功能:
所以,如果这是你想要完成的,那么它完全没问题,你也可以在jsFiddle之外使用它。对我来说,它看起来有点混乱,因为你失去了对整个(联合函数)的精确动画的控制,因为你为参数增加了额外的复杂度。换句话说:编程变得更难,因为你不确切知道结果会是什么。
我希望能回答你最后的兴趣点:)
快乐的节目!
demrks
问为什么宽松功能对其参数有限制。
让我们考虑一下easing
函数:
function easeOutBounce(x, t, b, c, d) {
if ((t/=d) < (1/2.75)) {
return c*(7.5625*t*t) + b;
} else if (t < (2/2.75)) {
return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
} else if (t < (2.5/2.75)) {
return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
} else {
return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
}
}
//x = null;
//t = currentTime;
//b = begin;
//c = end;
//d = distance;
通过查看函数,我们得出以下结论:
c=0
,则该函数将返回值b
b<0
和c=0
,则该函数将返回负值b
c<0
,则该函数将返回负值请注意,我们已将不透明度定义为:
"opacity": 1-scrollTransition(0, 1, 0, 400, scrollTop, "easeInSine", 1)
因此,如果函数scrollTransition(0, 1, 0, 400, scrollTop, "easeInSine", 1)
返回负值,我们将在$(".element").css(...);
属性中出错,因此不会发生任何事情。
所以基本上缓和函数工作正常。如果您将它们应用于属性不透明度,我们有时会有约束:
endValue > 0
谈到功能的行为,让我们考虑另一个:
function easeInOutElastic(x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
}
请注意,对于这个,该函数高度依赖于变量d
(距离)。
因此,公式运作良好。
只是您必须小心 如何应用它们以及 它们的行为方式可能会使事情变得复杂。
关于在jsFiddle中工作,请非常小心如何初始化文档。
例如,我发现使用缓动从-300
到200
的动画效果正常 IF ,您将document width
放大到动画空间< / strong>(动画需要正确执行的空间)。
您可以看到从-300
到200
here的动画制作代码。
请注意,我更改了文档宽度:
body {
height: 2000px;
width: 800px;
}
那应该回答你的问题。祝你好运!
要缩短switch statement
,您还可以使用:
var call = eval(easingEffect);
sum += call(null, scrollTop, startValue, endValue, distance);
正如您在THIS示例中所看到的那样。这可能会为您节省一些手工工作。