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

2020-09-04 23:27:29 +08:00
 AlphaRobert

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

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

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

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

有可以支的招吗?

2686 次点击
所在节点    JavaScript
6 条回复
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
2020-09-06 05:00:09 +08:00
不知道这个有没有用

window.scrollTo({
behavior: "smooth"
})
AlphaRobert
2020-09-06 10:57:19 +08:00
@w3cfed 这个只是平滑滚动,但是意图在持续触发 wheel 事件时,预测滚动终点,并在一连串事件结束后能吸附到最近的整格(例如 Apple Watch 的 TableView )
w3cfed
2020-09-06 11:07:31 +08:00
@AlphaRobert 这个我就不会啦
xiaoming1992
2020-09-06 23:17:04 +08:00
“对了,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
2020-09-07 07:17:52 +08:00
可以触控的 有 start 和 end 事件,可以对动画结束。
wheel 事件,用 setTimeout 来模拟结束事件

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/704359

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX