为什么这个 "scroll to top" 函数有问题?
Why is this "scroll to top" function glitchy?
我一直在寻找一个很好的解决方案,可以通过单击以动画方式将 div
(当然是可滚动的)滚动到其顶部。我遇到了 this(#2 解决方案),这看起来不错,但它滚动整个 window 而不是特定的 div
.
我稍微修改了此函数,使其可以滚动容器而不是整个容器 window。这是我的版本:
function scrollContainerToTop(scrollDuration, container_id) {
const container = document.getElementById(container_id),
scrollHeight = container.scrollTop,
scrollStep = Math.PI / (scrollDuration / 15),
cosParameter = scrollHeight / 2;
var scrollCount = 0,
scrollMargin,
scrollInterval = setInterval(function () {
if (container.scrollTop != 0) {
scrollCount = scrollCount + 1;
scrollMargin = cosParameter - cosParameter * Math.cos(scrollCount * scrollStep);
container.scrollTop = (scrollHeight - scrollMargin);
} else clearInterval(scrollInterval);
}, 15);
}
和 here 是一个功能示例,您可以尝试:将所有 "Hello" 的部分滚动到底部,然后单击按钮将其向上滚动 javascript.
所以我的问题是,它不是仅仅向上滚动,而是快速上下滚动两到三遍,然后才停在顶部。但是,如果您以更大的延迟(例如 300 毫秒)调用滚动条函数,那么一切都很好。我在 Safari、Chrome 和旧版本的 Firefox 上也尝试过,它们中的每一个都会产生相同的故障结果。
如果我提供更快的滚动时间,为什么这个函数会出现故障?
快速检查调试器(仔细放置 console.log)将回答以下问题:
function scrollContainerToTop(scrollDuration, container_id) {
const container = document.getElementById(container_id),
scrollHeight = container.scrollTop,
scrollStep = Math.PI / (scrollDuration / 15),
cosParameter = scrollHeight / 2;
var scrollCount = 0,
scrollMargin,
scrollInterval = setInterval(function () {
if (container.scrollTop != 0) {
scrollCount = scrollCount + 1;
scrollMargin = cosParameter - cosParameter * Math.cos(scrollCount * scrollStep);
container.scrollTop = (scrollHeight - scrollMargin);
// debug here:
console.log( 'container.scrollTop = ' + container.scrollTop );
} else clearInterval(scrollInterval);
}, 150);
}
结果:
container.scrollTop = 554
container.scrollTop = 465
container.scrollTop = 338
container.scrollTop = 202
container.scrollTop = 85
container.scrollTop = 14
container.scrollTop = 3
container.scrollTop = 55
container.scrollTop = 159
container.scrollTop = 293
container.scrollTop = 426
container.scrollTop = 530
container.scrollTop = 582
container.scrollTop = 571
container.scrollTop = 500
container.scrollTop = 383
container.scrollTop = 247
container.scrollTop = 120
container.scrollTop = 31
container.scrollTop = 0
更完整的解释:
当你未能达到 0 时,下一次迭代实际上会产生一个负数 scrollMargin
(因为那是 how cosine works)。迭代继续来回直到你最终达到 0。
看看当我们输出变量的实际值时会发生什么:
console.log( 'scrollMargin = ' + cosParameter + ' - ' + cosParameter + ' * ' + Math.cos(scrollCount * scrollStep) );
scrollMargin = 293 - 293 * 0.8910065241883679
scrollMargin = 293 - 293 * 0.5877852522924731
scrollMargin = 293 - 293 * 0.15643446504023092
scrollMargin = 293 - 293 * -0.30901699437494734
scrollMargin = 293 - 293 * -0.7071067811865475
scrollMargin = 293 - 293 * -0.9510565162951535
scrollMargin = 293 - 293 * -0.9876883405951378
scrollMargin = 293 - 293 * -0.8090169943749475
scrollMargin = 293 - 293 * -0.4539904997395469
scrollMargin = 293 - 293 * -1.8369701987210297e-16
scrollMargin = 293 - 293 * 0.45399049973954664
scrollMargin = 293 - 293 * 0.8090169943749472
scrollMargin = 293 - 293 * 0.9876883405951377
scrollMargin = 293 - 293 * 0.9510565162951536
scrollMargin = 293 - 293 * 0.7071067811865477
scrollMargin = 293 - 293 * 0.30901699437494773
scrollMargin = 293 - 293 * -0.15643446504022968
scrollMargin = 293 - 293 * -0.5877852522924729
scrollMargin = 293 - 293 * -0.8910065241883681
scrollMargin = 293 - 293 * -1
一种解决方案是简单地检查结果 container.scrollTop。如果您在 scrollMargin 范围内,则继续并完成滚动:
if (container.scrollTop < scrollMargin) container.scrollTop = 0;
我一直在寻找一个很好的解决方案,可以通过单击以动画方式将 div
(当然是可滚动的)滚动到其顶部。我遇到了 this(#2 解决方案),这看起来不错,但它滚动整个 window 而不是特定的 div
.
我稍微修改了此函数,使其可以滚动容器而不是整个容器 window。这是我的版本:
function scrollContainerToTop(scrollDuration, container_id) {
const container = document.getElementById(container_id),
scrollHeight = container.scrollTop,
scrollStep = Math.PI / (scrollDuration / 15),
cosParameter = scrollHeight / 2;
var scrollCount = 0,
scrollMargin,
scrollInterval = setInterval(function () {
if (container.scrollTop != 0) {
scrollCount = scrollCount + 1;
scrollMargin = cosParameter - cosParameter * Math.cos(scrollCount * scrollStep);
container.scrollTop = (scrollHeight - scrollMargin);
} else clearInterval(scrollInterval);
}, 15);
}
和 here 是一个功能示例,您可以尝试:将所有 "Hello" 的部分滚动到底部,然后单击按钮将其向上滚动 javascript.
所以我的问题是,它不是仅仅向上滚动,而是快速上下滚动两到三遍,然后才停在顶部。但是,如果您以更大的延迟(例如 300 毫秒)调用滚动条函数,那么一切都很好。我在 Safari、Chrome 和旧版本的 Firefox 上也尝试过,它们中的每一个都会产生相同的故障结果。
如果我提供更快的滚动时间,为什么这个函数会出现故障?
快速检查调试器(仔细放置 console.log)将回答以下问题:
function scrollContainerToTop(scrollDuration, container_id) {
const container = document.getElementById(container_id),
scrollHeight = container.scrollTop,
scrollStep = Math.PI / (scrollDuration / 15),
cosParameter = scrollHeight / 2;
var scrollCount = 0,
scrollMargin,
scrollInterval = setInterval(function () {
if (container.scrollTop != 0) {
scrollCount = scrollCount + 1;
scrollMargin = cosParameter - cosParameter * Math.cos(scrollCount * scrollStep);
container.scrollTop = (scrollHeight - scrollMargin);
// debug here:
console.log( 'container.scrollTop = ' + container.scrollTop );
} else clearInterval(scrollInterval);
}, 150);
}
结果:
container.scrollTop = 554
container.scrollTop = 465
container.scrollTop = 338
container.scrollTop = 202
container.scrollTop = 85
container.scrollTop = 14
container.scrollTop = 3
container.scrollTop = 55
container.scrollTop = 159
container.scrollTop = 293
container.scrollTop = 426
container.scrollTop = 530
container.scrollTop = 582
container.scrollTop = 571
container.scrollTop = 500
container.scrollTop = 383
container.scrollTop = 247
container.scrollTop = 120
container.scrollTop = 31
container.scrollTop = 0
更完整的解释:
当你未能达到 0 时,下一次迭代实际上会产生一个负数 scrollMargin
(因为那是 how cosine works)。迭代继续来回直到你最终达到 0。
看看当我们输出变量的实际值时会发生什么:
console.log( 'scrollMargin = ' + cosParameter + ' - ' + cosParameter + ' * ' + Math.cos(scrollCount * scrollStep) );
scrollMargin = 293 - 293 * 0.8910065241883679
scrollMargin = 293 - 293 * 0.5877852522924731
scrollMargin = 293 - 293 * 0.15643446504023092
scrollMargin = 293 - 293 * -0.30901699437494734
scrollMargin = 293 - 293 * -0.7071067811865475
scrollMargin = 293 - 293 * -0.9510565162951535
scrollMargin = 293 - 293 * -0.9876883405951378
scrollMargin = 293 - 293 * -0.8090169943749475
scrollMargin = 293 - 293 * -0.4539904997395469
scrollMargin = 293 - 293 * -1.8369701987210297e-16
scrollMargin = 293 - 293 * 0.45399049973954664
scrollMargin = 293 - 293 * 0.8090169943749472
scrollMargin = 293 - 293 * 0.9876883405951377
scrollMargin = 293 - 293 * 0.9510565162951536
scrollMargin = 293 - 293 * 0.7071067811865477
scrollMargin = 293 - 293 * 0.30901699437494773
scrollMargin = 293 - 293 * -0.15643446504022968
scrollMargin = 293 - 293 * -0.5877852522924729
scrollMargin = 293 - 293 * -0.8910065241883681
scrollMargin = 293 - 293 * -1
一种解决方案是简单地检查结果 container.scrollTop。如果您在 scrollMargin 范围内,则继续并完成滚动:
if (container.scrollTop < scrollMargin) container.scrollTop = 0;