只用 Javascript 怎么实现平滑的 scroll snap? - V2EX
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 3304 次点击
    这是一个创建于 1938 天前的主题,其中的信息可能已经有所发展或是发生改变。

    排除 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  
    &bsp;  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     Solana     5406 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 02:48 PVG 10:48 LAX 18:48 JFK 21:48
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86