在部分浏览器(例如:safari)下,手指触发滚动后抬起,此时元素会处于弹性滚动过程,此时这部分浏览器依旧能 实时 监听到滚动事件并做出响应,另外一部分浏览器(例如:UC及微信内嵌浏览器等),当抬手让元素处于弹性滚动过程时,浏览器并不能实时进行事件响应,而是当滚动完全停止后浏览器才会执行事件回调
在ios设备上,为了节约设备事件开销,window.onscroll 触发频率极低,只在停止滚动或页面回到顶部、底部才触发,有时甚至不触发。
后来去google了这方面的文章,几乎都说用 touchmove 代替 scroll,但是这有一个问题,就是 touchmove 的触发频率依旧不如 scroll 的
频率高,当然最重要的问题是,当 touchmove 结束的时候,ios 的页面具有一个类似于惯性的滑动特性,此时发生的滚动,既不能被
window.onscroll 捕获,也不不会执行 touchmove 的代码,甚是蛋疼。
再次,我查到了很多文章说,从 ios8.0 之后苹果放开了 scroll 的触发频率,但是事实摆在眼前,ios8.0后确实会触发大部分事件;但是涉及到fixed定位的元素则不会重新绘制,直到滑动停止才会重新绘制dom(亲测).
我想到的最简单的办法,就是setInterval, 模拟 scroll 的不间断询问过程。
后来发现,这个方法,行不通。因为 iOS 虽然不会暂停JavaScript执行,但它会暂停绘制。因此,应用程序的JavaScript将继续运行,
但是在滚动操作完成之前,DOM的任何更改都不会被绘制。所以,即使我们监听到了页面发生了滚动,我们也可以进行运算,
但是我们对页面上的元素展现无能为力。无论我们做什么,在滚动停止之前都不会绘制到页面上。
touchmove 的触发频率没有 scroll 的频率高,貌似 scroll 每 10px 就会触发一次,但是touchmove 的触发频率似乎与手指移动的距离
有关?但是对于我们监听滑动事件,它的触发频率已经足够高了。
但是 touchmove 事件有一个十分致命的缺点,就是当手指滑动的比较快的时候,手指离开屏幕的时候,滑动并未停止,还是会继续惯性
的滑动一段距离。这个时候,我们是没有办法对这个惯性进行控制的。当然,好消息是,我们可以关闭这个惯性效果:
-webkit-overflow-scrolling
属性控制元素在移动设备上是否使用滚动回弹效果.auto :使用普通滚动, 当手指从触摸屏上移开,滚动会立即停止。
touch :
使用具有回弹效果的滚动, 当手指从触摸屏上移开,内容会继续保持一段时间的滚动效果。继续滚动的速度和持续的时间和滚动手势的强烈程度成正比。同时也会创建一个新的堆栈上下文。
但是,上面这么做,虽然可以解决问题,但是会使滑动没有之前的那么灵动。总体来说,可行但是不太完美。
解释一下,通过touchmove,可以精确的控制用户在滑动的时候是会不断的触发滚动事件,并作出响应的。至于滑动后的惯性滑动,
则可以交给 scroll 来处理,应为scroll 正好可以在滚动结束的时候触发一次,这一次触发,刚好可以解决惯性带来的问题。
其实,我们正则匹配 agent 里面的 ios 或者 safari,然后针对这些设备绑定 touchmove 事件,
用于解决安卓 既会触发touch又会触发scroll的尴尬。
至于安卓和chrome,人家很好,不用关心。。。
scroll
方案行不通,但IOS提供了另一种方式:position: sticky
,自IOS 6.1就支持了,最近Chrome56才支持
没有滚过初始位置时,和position: relative
表现类似(占据空间,!static
能为后代元素提供定位参照),但top
和left
无效
滚过初始位置时,和position: fixed
表现类似,top
和left
生效,固定在屏幕可见区域,但页面不会抖动,
原本占据的空间还在(自带守家占位符的感觉)
但是IOS sticky不由我们控制,且 无法实时获知吸顶状态 ,想要获知吸顶状态的话,又回到了最初的问题,页面滚动过程中, 怎样实时获知滚动条位置?CSS sticky
并不能解决这个问题
祭出终极解决方案:iscroll!或者完全禁用本机滚动,并使用JavaScript来模仿滚动。
iScroll 大体是通过 CSS translation 此类的技术实现的滚动,便于安装和引入,既能够实现平滑的滚动,又可以持续不断的触发滚动事件。