【问题标题】:Detecting when finger is removed from touchpad but scroll is still happening due to "predictive touch" - JS检测手指何时从触摸板上移开但由于“预测触摸”而滚动仍在发生 - JS
【发布时间】:2020-04-23 23:16:22
【问题描述】:

我有一个函数可以处理每个时间段的滚动。此功能在用户使用鼠标滚轮滚动时起作用:

let shouldHandle = true
window.addEventListener('wheel', e => {
    if (shouldHandle) {
        handleScroll(e) // I will handle scrolls here
        shouldHandle = false
        setTimeout(() => {
            shouldHandle = true
        }, 750)
    }
})

但是,当我使用笔记本电脑的触摸板滚动时,即使我移开手指,滚动仍然会发生(尤其是当我将手指加速到足够的速度并滚动,然后立即将手指从触摸板上移开时)。因此,即使用户在技术上没有滚动,滚动仍然会在 750ms 之后发生。这个问题已被问到here。该问题未收到处理此行为的答案。

我只想在上次滚动后经过一段时间后处理滚动。我要处理的滚动一定不是因为这种“预测触摸”滚动引起的滚动。目前有没有办法做到这一点?

【问题讨论】:

    标签: javascript


    【解决方案1】:

    处理这个问题的唯一方法是在您看到滚动开始后观看scrollY 一段时间(轮询,可能每 50 毫秒左右)并等待它稳定下来(X 毫秒在同一位置,无论您决定 X 的任何值),然后才考虑滚动“完成”并启动您的 750 毫秒计时器。不断地轮询会很糟糕,但是在滚动仍然活跃的情况下进行短暂的轮询似乎是可以接受的。

    粗略的草图(例如,可能会使用整体超时):

    // VERY ROUGHLY
    let shouldHandle = true
    let lastScrollY = null
    let lastScrollTimer = 0
    window.addEventListener('wheel', e => {
        if (shouldHandle) {
            handleScroll(e) // I will handle scrolls here
            shouldHandle = false
            waitForScrollEnd(() => {
                setTimeout(() => {
                    shouldHandle = true
                }, 750) // Or perhaps 700 on the basis that up to 50 was spent in `waitForScrollToEnd`
            })
        }
    })
    function waitForScrollEnd(cb) {
        clearTimeout(lastScrollTimer)
        lastScrollY = window.scrollY
        lastScrollTimer = setTimeout(poll, 50)
    
        function poll() {
            if (lastScrollY === window.scrollY) {
                lastScrollY = null
                lastScrollTimer = 0 // This is entirely optional but makes it parallel with the `else` below
                cb()
            } else {
                lastScrollY = window.scrollY
                lastScrollTimer = setTimeout(poll, 50)
            }
        }
    }
    

    【讨论】:

    • 我认为代码应该在最后第四行之前插入这一行:lastScrollY = window.scrollY。另外,这段代码意味着不是由“预测触摸”引起的连续滚动(而是因为用户真的在滚动)不被处理,对吧?
    • @Richard - 恐怕我不知道你所说的“最后第四行是什么意思。我很确定 lastScrollY = window.scrollY 不需要它不在的任何地方上面。是的,waitForScrollEnd 将等待滚动结束,不管它为什么正在进行。
    • @Richard - (我认为这与您的评论无关。)以新的眼光看着上面的内容,在我看来,如果有新事件发生,它似乎想取消以前的 waitForScrollEnd我已经添加了,但无论如何它实际上只是一个调整......
    • 啊我的意思是:你的代码之前只调用一次waitForScrollEnd,这是用户第一次滚动的时候。之后,waitForScrollEnd 只会更新一次lastScrollY,但每 50 毫秒调用一次poll。但是,由于lastScrollY 只更新一次,所以即使滚动停止,poll 也会每 50 毫秒持续调用一次。
    • @Richard-Doh!!固定的。 :-)(倒数第四,我现在明白了。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多