我创建了一个简单的函数,该函数根据当前滚动位置为值设置动画。

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")
});


像这样根本不可能吗?还是我必须坚持线性过渡?

在此先感谢您的帮助和时间。

最佳答案

更新:

好吧,我花了一些时间,但我想我明白了。因为您创建了自己的“自定义”功能,所以很难完成。

直觉

为了解释我所做的一切,让我们从线性公式的绝对基础开始。


假设我们可以将您的自定义函数可视化为线性函数f(x)=x
假设我们可以将缓动函数可视化为非线性函数。例如,假设我们将函数g(x)=sin(x)视为缓动函数(这与缓动方法easeInSine相对应)


让我们在二维图中考虑这些功能:



如您所见,我现在绘制了两个不同的函数。如果我们将这些函数可视化为JavaScript中的函数,则它们是我们可以独立调用的两个独立函数。例如:

function linear(x)
{
   return x;
}

function sin(x)
{
   return Math.sin(x);
}


现在我们可以将这两个函数都用作scrollTransition,但这不是我们想要的。

您问了一个具体问题:如何将非线性函数添加到自定义线性函数中?

因此,让我们考虑一下我们的两个功能所具有的一些可能性:


我们可以将它们加在一起
我们可以减去它们
我们无能为力
我们可以取平均值
等等...


让我们形象化第一点:



灰色线表示原始功能,蓝色线表示添加在一起的功能。

对于第二点,我们将得到:



同样,灰线表示原始功能,蓝线表示添加在一起的功能。 (嗯……在这种情况下:“彼此相减”)

编码

让我们考虑一下我们所知道的一切:


我们知道您的函数会返回一定的线性确定值
我们知道缓动函数会返回一定的非线性确定值


因此,就像图形一样,我们可以添加和减去这些值以将函数添加在一起。

为了通过您的函数完成此操作,我在您的函数中添加了两个参数:


easingEffect应该是要从自定义函数中添加(或减去)的非线性缓动效果的名称
plus可以取值-101,并将确定如何处理非线性效应:


-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'来确保值始终不大于1。请注意,减法应该保持一致或添加非线性函数。

另外,如果您向下滚动javascript,您将看到所有功能和巨大的switch语句:您必须将所有这些功能添加到最终的javascript文件中。

所以我建议您将整个javascript部分复制到自己的项目中。

此外,jsFiddle应该是不言自明的。

祝你好运,我希望我回答了你的问题!

更新2

demrks执行以下操作:

sum = easeOutBounce(null, sum, startValue, endValue, distance);


要获得有关将参数sum添加到缓动函数的更多直观信息,请考虑下图:



蓝线表示功能的结果。

因此,您的基本操作被称为缓动函数的linear transformation或缓动函数的linear mapping。您可以阅读有关此here的更多信息。

但是基本上可以归结为,您正在通过以下属性来更改缓动函数的“形式”:


缓动动画“运行”的速度有多快
何时开始/终止


因此,如果这是您要完成的工作,那么它就很好了,您也可以在jsFiddle之外使用它。在我看来,这似乎有些混乱,因为您由于对参数增加了额外的复杂性而无法控制整个动画(关节函数)的精确动画。换句话说:编程变得更加困难,因为您不确定确切的结果。

我希望也能回答您的最后一个兴趣点:)

编程愉快!

更新3

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<0c=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有什么问题

关于在jsFiddle中工作,请特别注意如何初始化文档。

例如,我发现,如果将-300设置为大于动画空间(动画需要正确执行的空间),则从200document width进行缓动动画效果很好。

您可以看到从-300200 here动画的工作代码。

请注意,我更改了文档宽度:

body {
    height: 2000px;
    width: 800px;
}


那应该回答你的问题。祝好运!

更新4

要缩短switch statement,您还可以使用:

var call = eval(easingEffect);
sum += call(null, scrollTop, startValue, endValue, distance);


如您在THIS示例中看到的。这样可以省去一些手工工作。

关于jquery - 向自定义动画功能添加缓动,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17471537/

10-12 15:00