当惯性滚动算法接近顶部或底部时,我该如何减速?
How can I decelerate my inertial scroll algorithm when it nears the top or bottom?
我在javascript.
中为鼠标滚轮写了一个小的惯性滚动算法
它非常适合我的需要,但是缺少一部分,我似乎无法获得所需的行为。
当用户滚动到容器的末尾时,无论是顶部还是底部。我想势头自然地减速停下来。目前它只是在碰到任一边缘时立即停止,无论它当前的速度如何。
这里没有 post 大量代码,我创建了一个小的 jsfiddle 来说明:
https://jsfiddle.net/o8xLw68L/8/
这是我当前代码的简化版本。如果您取消注释行 111
如果您从 div
的顶部向下滚动一点然后相当快速地向上轻弹鼠标滚轮,您可以看到我正在寻找的行为。您会看到 0
位置的动量自然减慢。
Inertial.prototype.smoothWheel = function(amt) {
this.targetY += amt;
//uncomment this line to see the decelleration almost work against the top edge of the container
//this.targetY = Math.max(0, this.targetY);
this.vy += (this.targetY - this.oldY) * this.stepAmt;
this.oldY = this.targetY;
}
这种方法的问题在于,它只会在鼠标滚轮脉冲时抑制结果 this.vy
属性,因此并不总是能正常工作,因为用户可能从容器的下方滚动, 并且速度更快,但没有任何持续的鼠标滚轮脉冲。 (这很难表达,jsFiddle应该更清楚)
当我们接近容器的顶部或底部时,解决方案可能需要以某种方式抑制 this.vy
属性,以便它以比自然速度更快的速度减速 this.friction
属性 允许。
当您到达内容的 top/bottom 的 300px
时,我很高兴阻尼区域被硬编码为。或者,容器高度的百分比也可以。
如有任何帮助,我们将不胜感激。
可以通过惯性运动(有摩擦力)将速度衰减到足以触摸顶部或底部边缘的值,而与鼠标滚轮速度无关。
假设在当前方向上行进的距离x
是给定的。因此,需要找到速度 v0
足以通过惯性运动和摩擦力行进该距离。
当前滚动动力学 (vy *= friction
) 对应于层流。可以写成微分方程:
dv = - (1 - friction) * v * dt; // velocity change dv in time interval dt
dv / v = - (1 - friction) * dt;
// integrating lhs and rhs with initial conditions (v = v0 at t = 0)
ln(v/v0) = - (1 - friction) * t;
v = v0 * exp(- (1 - friction) * t);
因此,速度随时间从 v0
呈指数衰减到零。
行驶距离:
dx = v * dt = v0 * exp(- (1 - friction) * t) * dt;
// integrating, initial conditions x = 0 at t = 0
x = v0 / (1 - friction) * (1 - exp(- (1 - friction) * t))
因此可以在无限时间内以起始速度v0
行进以下距离:
x = v0 / (1 - friction);
基于到边缘的距离,可以限制速度:
Inertial.prototype.boundVelocity = function () {
var dist = 0;
if (this.dir == 1)
dist = this.scrollerPos;
else if (this.dir == -1)
dist = this.contentHeight - this.scrollerHeight - this.scrollerPos;
var maxv = dist * (1 - this.friction) + 1;
if (Math.abs(this.vy) > maxv) {
console.log('reduce velocity ' + this.vy + ' to ' + (-maxv * this.dir) + ', dist: ' + dist);
this.vy = -maxv * this.dir;
}
}
maxv
(+1
) 有一些小的非零最小值,以确保边缘总是被击中,尽管存在离散化错误。当速度可以在 smoothWheel()
中增加时调用该函数,并且在 render()
中调用它只是为了避免数值误差累积。
我在javascript.
中为鼠标滚轮写了一个小的惯性滚动算法它非常适合我的需要,但是缺少一部分,我似乎无法获得所需的行为。
当用户滚动到容器的末尾时,无论是顶部还是底部。我想势头自然地减速停下来。目前它只是在碰到任一边缘时立即停止,无论它当前的速度如何。
这里没有 post 大量代码,我创建了一个小的 jsfiddle 来说明:
https://jsfiddle.net/o8xLw68L/8/
这是我当前代码的简化版本。如果您取消注释行 111
如果您从 div
的顶部向下滚动一点然后相当快速地向上轻弹鼠标滚轮,您可以看到我正在寻找的行为。您会看到 0
位置的动量自然减慢。
Inertial.prototype.smoothWheel = function(amt) {
this.targetY += amt;
//uncomment this line to see the decelleration almost work against the top edge of the container
//this.targetY = Math.max(0, this.targetY);
this.vy += (this.targetY - this.oldY) * this.stepAmt;
this.oldY = this.targetY;
}
这种方法的问题在于,它只会在鼠标滚轮脉冲时抑制结果 this.vy
属性,因此并不总是能正常工作,因为用户可能从容器的下方滚动, 并且速度更快,但没有任何持续的鼠标滚轮脉冲。 (这很难表达,jsFiddle应该更清楚)
当我们接近容器的顶部或底部时,解决方案可能需要以某种方式抑制 this.vy
属性,以便它以比自然速度更快的速度减速 this.friction
属性 允许。
当您到达内容的 top/bottom 的 300px
时,我很高兴阻尼区域被硬编码为。或者,容器高度的百分比也可以。
如有任何帮助,我们将不胜感激。
可以通过惯性运动(有摩擦力)将速度衰减到足以触摸顶部或底部边缘的值,而与鼠标滚轮速度无关。
假设在当前方向上行进的距离x
是给定的。因此,需要找到速度 v0
足以通过惯性运动和摩擦力行进该距离。
当前滚动动力学 (vy *= friction
) 对应于层流。可以写成微分方程:
dv = - (1 - friction) * v * dt; // velocity change dv in time interval dt
dv / v = - (1 - friction) * dt;
// integrating lhs and rhs with initial conditions (v = v0 at t = 0)
ln(v/v0) = - (1 - friction) * t;
v = v0 * exp(- (1 - friction) * t);
因此,速度随时间从 v0
呈指数衰减到零。
行驶距离:
dx = v * dt = v0 * exp(- (1 - friction) * t) * dt;
// integrating, initial conditions x = 0 at t = 0
x = v0 / (1 - friction) * (1 - exp(- (1 - friction) * t))
因此可以在无限时间内以起始速度v0
行进以下距离:
x = v0 / (1 - friction);
基于到边缘的距离,可以限制速度:
Inertial.prototype.boundVelocity = function () {
var dist = 0;
if (this.dir == 1)
dist = this.scrollerPos;
else if (this.dir == -1)
dist = this.contentHeight - this.scrollerHeight - this.scrollerPos;
var maxv = dist * (1 - this.friction) + 1;
if (Math.abs(this.vy) > maxv) {
console.log('reduce velocity ' + this.vy + ' to ' + (-maxv * this.dir) + ', dist: ' + dist);
this.vy = -maxv * this.dir;
}
}
maxv
(+1
) 有一些小的非零最小值,以确保边缘总是被击中,尽管存在离散化错误。当速度可以在 smoothWheel()
中增加时调用该函数,并且在 render()
中调用它只是为了避免数值误差累积。