V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
AlphaRobert
V2EX  ›  JavaScript

只用 JavaScript 怎么实现平滑的 scroll snap?

  •  
  •   AlphaRobert · 2020-09-04 23:27:29 +08:00 · 2887 次点击
    这是一个创建于 1569 天前的主题,其中的信息可能已经有所发展或是发生改变。

    排除 CSS 的 scroll-snap,在 Safari 下会奇怪地带动 body 或其他先祖元素滚动,且浏览器兼容也不好。

    如果有强迫症的话,定时一段时间检测滚动停止后,再滚动到最近的位置不是很丝滑。假设内容为一堆 24px 高的列表项目:

    对于触控,在 scrollend 时计算出最后一小段时间的加速度,然后平滑滚动到对应的位置就可以。

    对于鼠标,因为不知道滚动什么时候停止,以及触控板和鼠标的滚动方式也千奇百怪,想到一个基本上不可行的方法:每次触发 wheel 事件后,根据最后一小段时间的 deltaY 和时间的关系插值,推测出滚动结束的时间和终点位置,记 positionOffset 为预期终点位置和最近元素坐标间的距离,time 为允许的缓冲时间,以 1px 为最小分度,每隔 Math.abs(positionOffset) / timescrollTop++--。数值发生变化时(什么数值?)取消之前的计时并重新计时。显然这很麻烦而且根本没有头绪。

    有可以支的招吗?

    6 条回复    2020-09-07 07:17:52 +08:00
    w3cfed
        1
    w3cfed  
       2020-09-06 02:00:38 +08:00
    ```javascript
    const scrollToTop = () => {
    const c = document.documentElement.scrollTop || document.body.scrollTop;
    if (c > 0) {
    window.requestAnimationFrame(scrollToTop);
    window.scrollTo(0, c - c / 8);
    }
    }

    scrollToTop()

    ```

    // 事例
    `window.requestAnimationFrame()`

    告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

    `requestAnimationFrame`

    优势:由系统决定回调函数的执行时机。60Hz 的刷新频率,那么每次刷新的间隔中会执行一次回调函数,不会引起丢帧,不会卡顿。

    来之整理博客内容 [How to scroll to the top of the page smoothly? ]( https://github.com/martinageradams/blog/issues/11)
    w3cfed
        2
    w3cfed  
       2020-09-06 05:00:09 +08:00
    不知道这个有没有用

    window.scrollTo({
    behavior: "smooth"
    })
    AlphaRobert
        3
    AlphaRobert  
    OP
       2020-09-06 10:57:19 +08:00
    @w3cfed 这个只是平滑滚动,但是意图在持续触发 wheel 事件时,预测滚动终点,并在一连串事件结束后能吸附到最近的整格(例如 Apple Watch 的 TableView )
    w3cfed
        4
    w3cfed  
       2020-09-06 11:07:31 +08:00
    @AlphaRobert 这个我就不会啦
    xiaoming1992
        5
    xiaoming1992  
       2020-09-06 23:17:04 +08:00 via Android
    “对了,Scroll Snap 有个 polyfill:css-scroll-snap-polyfill

    “可以让 Chrome 63,Firefox 57,Safari 11 浏览器都有效果。”

    节选自 https://www.zhangxinxu.com/wordpress/2018/11/know-css-scroll-snap/
    ccraohng
        6
    ccraohng  
       2020-09-07 07:17:52 +08:00 via iPhone
    可以触控的 有 start 和 end 事件,可以对动画结束。
    wheel 事件,用 setTimeout 来模拟结束事件
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2786 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 11:41 · PVG 19:41 · LAX 03:41 · JFK 06:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.