http://blog.hooperui.com/%E5%85%B3%E4%BA%8Eios%E8%AE%BE%E5%A4%87window-onscroll%E6%BB%9A%E5%8A%A8%E6%9D%A1%E6%BB%9A%E5%8A%A8%E4%BA%8B%E4%BB%B6%E4%B8%8D%E8%A7%A6%E5%8F%91%E7%9A%84%E9%97%AE%E9%A2%98/

这两天遇到一个奇葩事,在ios设备上,为了节约设备事件开销,window.onscroll 触发频率极低,只在停止滚动或页面回到顶部、底部才触发,有时甚至不触发。。。

后来去google了这方面的文章,几乎都说用 touchmove 代替 scroll,但是这有一个问题,就是 touchmove 的触发频率依旧不如 scroll 的频率高,当然最重要的问题是,当 touchmove 结束的时候,ios 的页面具有一个类似于惯性的滑动特性,此时发生的滚动,既不能被 window.onscroll 捕获,也不不会执行 touchmove 的代码,甚是蛋疼。

再次,我查到了很多文章说,从 ios8.0 之后苹果放开了 scroll 的触发频率,但是事实摆在眼前,人家确实不会触发啊。。。。总不能苹果放开之后觉得不妥,又改回去了?(参考文章很多,我这里提供一篇 http://developer.telerik.com/featured/scroll-event-change-ios-8-big-deal/)

经过数次研究,仍然不能解决这个问题,但是后来得到了几个套路:

本文文章目录 [hide]
1.setInterval
2.使用 touchmove 代替 scroll
3.touchmove+scroll(我正在使用的)
4.模拟滚动
5. 特殊情况。
1.setInterval

我想到的最简单的办法,就是setInterval, 模拟 scroll 的不间断询问过程。

后来发现,这个方法,行不通。因为 iOS 虽然不会暂停JavaScript执行,但它会暂停绘制。因此,应用程序的JavaScript将继续运行,但是在滚动操作完成之前,DOM的任何更改都不会被绘制。所以,即使我们监听到了页面发生了滚动,我们也可以进行运算,但是我们对页面上的元素展现无能为力。无论我们做什么,在滚动停止之前都不会绘制到页面上。

2.使用 touchmove 代替 scroll

touchmove 的触发频率没有 scroll 的频率高,貌似 scroll 每 10px 就会触发一次,但是touchmove 的触发频率似乎与手指移动的距离有关?但是对于我们监听滑动事件,它的触发频率已经足够高了。

但是 touchmove 事件有一个十分致命的缺点,就是当手指滑动的比较快的时候,手指离开屏幕的时候,滑动并未停止,还是会继续惯性的滑动一段距离。这个时候,我们是没有办法对这个惯性进行控制的。当然,好消息是,我们可以关闭这个惯性效果:

-webkit-overflow-scrolling 属性控制元素在移动设备上是否使用滚动回弹效果.

auto :使用普通滚动, 当手指从触摸屏上移开,滚动会立即停止。

touch :使用具有回弹效果的滚动, 当手指从触摸屏上移开,内容会继续保持一段时间的滚动效果。继续滚动的速度和持续的时间和滚动手势的强烈程度成正比。同时也会创建一个新的堆栈上下文。

-webkit-overflow-scrolling: touch; /* 当手指从触摸屏上移开,会保持一段时间的滚动 */
-webkit-overflow-scrolling: auto; /* 当手指从触摸屏上移开,滚动会立即停止 */
但是,上面这么做,虽然可以解决问题,但是会使滑动没有之前的那么灵动。总体来说,可行但是不太完美。所以我也没有使用这个方法。

3.touchmove+scroll(我正在使用的)

(“#page1”).on(‘touchmove’, function () {  
    // do something  
});  
//ps:我真的已经尽力了。。但是ios对于scroll的触发频率太低了,只在停止滚动或页面回到顶部、底部才触发,希望后来者居上,能够修复这个问题。 (“#page1”).on(‘touchmove’, function () {      // do something  });  //ps:我真的已经尽力了。。但是ios对于scroll的触发频率太低了,只在停止滚动或页面回到顶部、底部才触发,希望后来者居上,能够修复这个问题。 (“#page1”).on(‘touchmove’, function () { // do something }); //ps:我真的已经尽力了。。但是ios对于scroll的触发频率太低了,只在停止滚动或页面回到顶部、底部才触发,希望后来者居上,能够修复这个问题。 (window).on(“scroll”, function (e) {
// do something
})
中间的注释我留着呢。。我真的想不到更好的解决办法了。。。

解释一下,通过touchmove,可以精确的控制用户在滑动的时候是会不断的触发滚动事件,并作出响应的。至于滑动后的惯性滑动,则可以交给 scroll 来处理,应为scroll 正好可以在滚动结束的时候触发一次,这一次触发,刚好可以解决惯性带来的问题。

其实,我们正则匹配 agent 里面的 ios 或者 safari,然后针对这些设备绑定 touchmove 事件, 用于解决安卓 既会触发touch又会触发scroll的尴尬。

至于安卓和chrome,人家很好,不用关心。。。

4.模拟滚动

祭出终极解决方案:iscroll!或者完全禁用本机滚动,并使用JavaScript来模仿滚动。

$(‘window’).on(‘touchmove’, function(event) {
//Prevent the window from being scrolled.
event.preventDefault();

//Do something like call window.scrollTo to mimic the scrolling
//request the user made.

});
iScroll 大体是通过 CSS translation 此类的技术实现的滚动,便于安装和引入,既能够实现平滑的滚动,又可以持续不断的触发滚动事件。可以解决我们的问题。

当然,如果你的项目框架迫使你不能引入第三方库的话,iScroll 可能就不能用了(这也是我没有使用的原因),但我们仍然可以使用上述代码,来模拟滚动。

  1. 特殊情况。

如果你是想制作一个在滚动时自动定在屏幕上方的区块(如下图),那么你可以分别针对安卓和ios设置不同的实现方式。

上图中,Iphone8的title刚加载时是在一个位置,但是当屏幕滚动后,会自动定位到屏幕的最上方,并固定住。如果是简单的实现这个功能,建议:

1、安卓上直接使用 scroll 的数值判定,并设置这个元素的position。(因为安卓上的css支持情况良莠不齐,且素质不高)

2、ios,推荐使用CSS的 sticky 属性。

设置了sticky的元素,在屏幕范围(viewport)时该元素的位置并不受到定位影响(设置是top、left等属性无效),当该元素的位置将要移出偏移范围时,定位又会变成fixed,根据设置的left、top等属性成固定位置的效果。

可以知道sticky属性有以下几个特点:

该元素并不脱离文档流,仍然保留元素原本在文档流中的位置。
当元素在容器中被滚动超过指定的偏移值时,元素在容器内固定在指定位置。亦即如果你设置了top: 50px,那么在sticky元素到达距离相对定位的元素顶部50px的位置时固定,不再向上移动。
元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素,如果祖先元素都不可以滚动,那么是相对于viewport来计算元素的偏移量
sticky的使用需要添加webkit前缀,支持情况如下:

关于IOS设备window onscroll滚动条滚动事件不触发的问题相关推荐

  1. jquery滚动条滚动事件_滚动条和jQuery –使用航点的事件处理

    jquery滚动条滚动事件 How to handle scrolling with jQuery. Today we continue jQuery reviews, and our article ...

  2. JS网页滚动条滚动事件实例分析

    js网页滚动条滚动事件的用法,在javascript中window.onscroll监控滚动条滚动事件的相关技巧 本文实例讲述了js网页滚动条滚动事件用法,具体分析如下: 在做js返回顶部的效果时,要 ...

  3. vue 监听页面滚动事件:触发animate.min.css动画特效

    一.问题答疑: 1. animate.css 如何在vue项目中引入?或引用? 2. 如何监听滚动事件,触发animate.class动画播放? vue 监听滚轮滚动事件,for循环 ,动态id,代码 ...

  4. window.scrollTo滚动条滚动速度 滚动到指定距离

    常用使用法: window.scrollTop(x,y)//x横坐标 y纵坐标例:window.scrollTop(0)window.scrollTop(100,0)window.scrollTop( ...

  5. window.onscroll 事件不触发问题

    要求:滚动鼠标时,触发滚动事件: 问题:滚动时,没有触发事件: html,body{overflow-x: hidden;font-size: 16px;color: #666;margin: 0 a ...

  6. 让div在页面居中(滚动条滚动时也居中)

    居中css: #timeWrap {position: absolute;width: 500px;height: 250px;left: 50%;top: 300px;margin-left: -2 ...

  7. vue 组件封装 | s-fullpage 全屏滚动 (内含绑定鼠标滑轮滚动事件、避免鼠标滑轮连续滚动、滑动过渡动画等实用技巧)

    目录 目标 实现原理(要点) 完整代码 s-fullpage 和 s-fullpageItem s-fullpage.vue s-fullpageItem.vue 使用范例 范例效果 目标 实现类似插 ...

  8. iframe页面里的链接在ios设备无法点击的解决办法

    2019独角兽企业重金招聘Python工程师标准>>> iframe页面,在ios设备浏览器里,滚动后,原来被隐藏的按钮或链接均无法点击,一点击就弹回左上角,可以用下面的方法修正这个 ...

  9. ios滚动条影响父页面 vue_在IOS系统上滚动条滚动到指定的位置出现空白页面的解决方案...

    在IOS系统上滚动条滚动到指定的位置出现空白页面的解决方案 原因: -webkit-overflow-scrolling:touch 解释: 由于使用-webkit-overflow-scrollin ...

最新文章

  1. golang sftp传输文件
  2. 【OpenStack】OpenStack系列1之OpenStack本地开发环境搭建向社区贡献代码
  3. 最大搜索二叉子树大小(树形dp)
  4. php程序中报date错误
  5. 数据库 Linux下的MySQL数据库管理
  6. 用Linux命令行生成随机密码的十种方法
  7. 税收分类编码2020_增值税开票系统你会吗?2020最新开票(金税盘版)图文教程详细版...
  8. ospfdr选举规则_ospf DR和BDR选举注意的问题
  9. 面向普通人的 PHP 加密
  10. mysql报1840_mysql 帮助手册 以及 warning: World-writable config file 以及 ERROR 1840 (HY000) at line 24:...
  11. Pytorch(0)降低学习率torch.optim.lr_scheduler.ReduceLROnPlateau类
  12. linux of命令,Linux命令(30):isof
  13. C#判断一个数是否为素数
  14. 时间管理之-----《暗时间》-刘未鹏
  15. h5大前端常用网站以及npm模块整理
  16. 功能超全的库存管理系统,拿来学习真香
  17. 【数据结构】红黑树入门知识
  18. ACPI Specification 第二章 条款的定义
  19. shell中的并且、和、或者
  20. Oracle用户名有引号,关于oracle sql 中as与双引号的一点有趣故事

热门文章

  1. 为远程群晖NAS的自定义域名配置SSL证书
  2. VSCode常用插件和字体设置
  3. 解决:Excel 下拉项数据报 输入内容不能大于255个字符
  4. @PageableDefault
  5. 阿里云服务器 API 的使用
  6. Chrome浏览器 设置跨域访问
  7. 一款Excel导入导出解决方案组成的轻量级开源组件
  8. Uni-app 小程序 APP 的广告变现之路:插屏广告
  9. 姓名拆分为姓氏和名字的方法
  10. 红帽 RHCSA笔记