为什么这个"滚动到顶部"功能故障?

时间:2015-03-25 02:54:14

标签: javascript html scroll

我一直在寻找一个很好的解决方案,只需点击一下,然后以动画的方式将div(当然可以滚动)滚动到顶部。我遇到了this(#2解决方案),看起来非常不错,但它滚动整个窗口而不是特定的div

我稍微修改了这个函数,以便它可以滚动容器而不是整个窗口。这是我的版本:

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" s滚动到底部,然后单击按钮以使用javascript向上滚动它。

所以我的问题是,它不是只是向上滚动,而是快速向上和向下滚动两到三次然后才能在顶部向上滚动。但是,如果你以更大的延迟(比如说300毫秒)调用滚动功能,那么一切都很好。我尝试使用Safari,Chrome和较旧版本的Firefox,并且每个版本都会产生相同的错误结果。

那么,如果我提供更快的滚动时间,为什么这个功能会出现故障呢?

1 个答案:

答案 0 :(得分:0)

快速检查调试器(使用精心放置的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;