为什么这个“滚动到顶部"?功能有问题? [英] Why is this "scroll to top" function glitchy?

查看:53
本文介绍了为什么这个“滚动到顶部"?功能有问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was looking for a good solution to scroll a div (that is scrollable of course) to its top, with a single click, and in an animated way. I came across this (the #2 solution), which seemed pretty good, but it scrolls the whole window instead of a specific div.

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

I slightly modified this function so that it can scroll a container instead of the whole window. Here's my version:

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

而且这里是一个功能示例,您可以尝试一下:滚动该部分Hello"s 到底部,然后单击按钮使用 javascript 向上滚动.

And here is a functional example, which you can try out: scroll the section with all the "Hello"s to the bottom, then click the button to scroll it up with javascript.

所以我的问题是,它不是向上滚动,而是快速向上和向下滚动两到三遍,然后才稳定在顶部.但是,如果您以更大的延迟(比如 300 毫秒)调用 scroller 函数,那么一切都很好.我也在 Safari、Chrome 和旧版本的 Firefox 上进行了尝试,但它们中的每一个都产生了相同的故障结果.

So my problem is that instead of just scrolling up, it scrolls up and down rapidly two or three times before settling on the top. However, if you call the scroller function with a bigger delay (say 300ms), then everything is fine. I tried it with Safari, Chrome, and an older version of Firefox as well, and every one of them produces the same glitchy result.

如果我提供更快的滚动时间,为什么这个函数会出现问题?

So why is this function glitchy if I supply it faster scroll times?

推荐答案

快速检查调试器(带有精心放置的 console.log)将回答这个问题:

A quick examination of the debugger (with a carefully placed console.log) will answer the question:

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(因为那是 余弦如何工作).不断地来回迭代,直到最终达到 0.

When you fail to reach 0, the next iteration will actually produce a negative scrollMargin (because that's how cosine works). The iteration continues back and forth until you finally reach 0.

看看当我们输出变量的实际值时会发生什么:

See what happens when we output the actual values of the variables:

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 范围内,请继续完成滚动:

One solution would be to simply check the resulting container.scrollTop. If you are within the scrollMargin, then just go ahead and complete the scroll:

if (container.scrollTop < scrollMargin) container.scrollTop = 0;

这篇关于为什么这个“滚动到顶部"?功能有问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆