我在我的网站上制作scrollTo
功能,并以this answer为基础。因为我不想只复制和粘贴代码,所以我试图理解它。除了scrollToX function
中的数学部分,我能够理解一切(花了我2天!)。
element.scrollTop = xFrom - (xFrom - xTo) * motion(t01);
t01 += speed * step;
我理解实际的数学,但我不明白为什么它有效。为什么这个数学会产生滚动动画?
document.getElementsByTagName('button')[0].onclick = function() {
scrollTo(0, 1000);
}
// Element to move, time in ms to animate
function scrollTo(element, duration) {
var e = document.documentElement;
if (e.scrollTop === 0) {
var t = e.scrollTop;
++e.scrollTop;
e = t + 1 === e.scrollTop-- ? e : document.body;
}
scrollToC(e, e.scrollTop, element, duration);
}
// Element to move, element or px from, element or px to, time in ms to animate
function scrollToC(element, from, to, duration) {
if (duration <= 0) return;
if (typeof from === "object") from = from.offsetTop;
if (typeof to === "object") to = to.offsetTop;
scrollToX(element, from, to, 0, 1 / duration, 20, easeOutCuaic);
}
function scrollToX(element, xFrom, xTo, t01, speed, step, motion) {
if (t01 < 0 || t01 > 1 || speed <= 0) {
element.scrollTop = xTo;
return;
}
element.scrollTop = xFrom - (xFrom - xTo) * motion(t01);
t01 += speed * step;
setTimeout(function() {
scrollToX(element, xFrom, xTo, t01, speed, step, motion);
}, step);
}
function linearTween(t) {
return t;
}
function easeInQuad(t) {
return t * t;
}
function easeOutQuad(t) {
return -t * (t - 2);
}
function easeInOutQuad(t) {
t /= 0.5;
if (t < 1) return t * t / 2;
t--;
return (t * (t - 2) - 1) / 2;
}
function easeInCuaic(t) {
return t * t * t;
}
function easeOutCuaic(t) {
t--;
return t * t * t + 1;
}
function easeInOutCuaic(t) {
t /= 0.5;
if (t < 1) return t * t * t / 2;
t -= 2;
return (t * t * t + 2) / 2;
}
function easeInQuart(t) {
return t * t * t * t;
}
function easeOutQuart(t) {
t--;
return -(t * t * t * t - 1);
}
function easeInOutQuart(t) {
t /= 0.5;
if (t < 1) return 0.5 * t * t * t * t;
t -= 2;
return -(t * t * t * t - 2) / 2;
}
function easeInQuint(t) {
return t * t * t * t * t;
}
function easeOutQuint(t) {
t--;
return t * t * t * t * t + 1;
}
function easeInOutQuint(t) {
t /= 0.5;
if (t < 1) return t * t * t * t * t / 2;
t -= 2;
return (t * t * t * t * t + 2) / 2;
}
function easeInSine(t) {
return -Mathf.Cos(t / (Mathf.PI / 2)) + 1;
}
function easeOutSine(t) {
return Mathf.Sin(t / (Mathf.PI / 2));
}
function easeInOutSine(t) {
return -(Mathf.Cos(Mathf.PI * t) - 1) / 2;
}
function easeInExpo(t) {
return Mathf.Pow(2, 10 * (t - 1));
}
function easeOutExpo(t) {
return -Mathf.Pow(2, -10 * t) + 1;
}
function easeInOutExpo(t) {
t /= 0.5;
if (t < 1) return Mathf.Pow(2, 10 * (t - 1)) / 2;
t--;
return (-Mathf.Pow(2, -10 * t) + 2) / 2;
}
function easeInCirc(t) {
return -Mathf.Sqrt(1 - t * t) - 1;
}
function easeOutCirc(t) {
t--;
return Mathf.Sqrt(1 - t * t);
}
function easeInOutCirc(t) {
t /= 0.5;
if (t < 1) return -(Mathf.Sqrt(1 - t * t) - 1) / 2;
t -= 2;
return (Mathf.Sqrt(1 - t * t) + 1) / 2;
}
Very long page.Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page.Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page. Very long page.
<button type="button">To the top</button>
答案 0 :(得分:2)
因此,您在示例中碰巧传递的运动函数是easeOutCubic
,其定义为
function easeOutCubic(t) {
t--;
return t * t * t + 1;
}
首先,每次调用speed * step
时,都会将{t}增加scrollToX
。由于这两个变量在函数范围内都是常数,t
将以恒定速率接近1。如果将t
递减1,它将始终产生大于-1的负数,因为该函数适用于(0,1)
区间。在您继续致电scrollToX
时,(t-1)^3 + 1
将以较慢的速率获得更大的但。这是因为当t
变得越来越大时,(t-1)
的绝对值会不断递减,而因为 (t-1)
总是小于0,{{1} }将以递减速率逼近0,因此(t-1)^3
将以相同的递减率接近1。对于所有(t-1)^3 + 1
d^2((t-1)^3)/dt^2 < 0
这一事实,可以更简洁地表达这一点,但决定提供更多的解释。
您可以将函数t < 1
视为0到1之间的因子,乘以最终的最终行进距离或motion(t)
,以找出特定时间点的总行进距离。
编辑(取自我删除的以下评论):
(xFrom-xTo)
是一个变量,其值与调用t
的次数成正比,并且因为scrollToX
在特定时间间隔(或多或少)被调用,价值是时间的函数。现在我们将该数字插入任何运动功能。现在让我们以scrollToX
为例,因为它只返回输入。
当您将linearTween
从0增加到.02到.04时,t
将以恒定速率增加。您可以乘以motion(t)
,这将产生介于0和1之间的数字(此值将随时间变化并最终达到值1)并将其乘以要行进的总距离motion(t)
,找到特定(xFrom-xTo)
的较短距离。您从原点t
中减去这个小于最终的距离,以获得特定xFrom
滚动条的位置。
视觉示例:
t
垂直条的第一列表示要移动的总距离,在这种情况下等于100.第二行垂直条表示当运动(t)= 0.6时任意行进的距离(任意选择) )。如果我们想要在motion(t)= 0.6时找到滚动条顶部的位置,我们必须计算200-(100)* 0.6,或者通常形成xTo = 100
|
|
||
||
||
xFrom = 200
。
答案 1 :(得分:2)
首先,让我引用Robert Penners动作的定义
动作是时间超过时间的数值变化。
以上可以写成:
pf = p0 + motion(time)
where:
- p0 = initial position
- pf = final position
运动只有在时间存在时才存在,因此它是时间的函数。由于从初始位置通过运动到达任何位置,我们也可以说位置是时间的函数所以
position = f(time)
以上是典型的y = f(x)
2d函数,让我们暂时假设函数是一条线并且运动发生超过1秒,该函数将被绘制为
该行的slope由
给出m = (pf - p0) / (1 - 0) = pf - p0 (1)
斜率将帮助我们在px
时找到0 < t < 1
,因为对于属于该线的任何两个点,斜率是相同的,因此
m = (px - p0) / (t - 0) = (px - p0) / t (2)
在(1)
中替换(2)
并找到px
pf - p0 = (px - p0) / t
t * (pf - p0) = px - p0
px = p0 + (pf - p0) * t
这与您的原始等式完全相同(减号由等式中的某种原因分解)
另请注意:
t = 0
则px = p0
t = 1
则px = pf
现在,t
的值为0 <= t <= 1
,我们知道t
,我们可以创建另一个依赖motion(t)
的函数,例如motion(0) = 0
motion(1) = 1
符合以下要求:
px
这些条件必须保持原始const linear = t => t
方程具有正确的值,最简单的运动函数是线性或同一性函数:
const quadratic = t => t * t
另一个功能是二次函数:
px = p0 + (pf - p0) * motion(t)
那么位置函数将是
t
最后,您会发现很多easing functions over the internet,因为我们知道t0
的价值会与经过的时间成比例增加,给定初始时间tf
我们可以计算下次tf = t0 + delta(t)
具有相同的动作定义
delta(t)
现在,如果你想加快/减慢你的动画,你只需要将k
与k > 1
相乘,如果k < 1
那么动画会更快{{1}因此动画会慢一些:
px = p0 + (pf - p0) * motion(t0)
tf = t0 + k * delta(t)
// the final time will be the initial time for the next iteration
t0 = tf
例如,如果您希望动画在0.5秒内发生(两倍快)k = 2
,如果持续时间为2.0秒(慢两倍)k = 0.5
,则查找值的公式然后是k
:
k = 1 / duration