滑动,对于移动端来讲多么简单的一个动做,上下动动手指头呗,就比如pc上的滚滚鼠标,你说动个手指头能弄出个啥大事儿啊...emmmm , 图样图森破, 没作过以前我也是这样想的 , 可是亲身碰到了那才叫一个酸爽٩(๑❛ᴗ❛๑)۶.css
此次的要求作一个局部区域滚动,页面结构大体分为上中下三个结构 , 上面是一个固定的黑色播放窗口,中间就是滚动区域,下面是一个操做导航;html
当时在chrome的手机模拟器上看的效果,没有发生任何问题,可是后面用真实手机一测...瞬间爆炸jquery
顶部一个固定的播放展现页,中奖评论交流,底部一个发送消息输入框,如图所示;
按照基本布局以后,在中间部分(mian)使用ios
.main{ overflow-y:scroll; -webkit-overflow-scrolling:touch; }
获得滚动效果,注意这2个属性,首先overflow-y:scroll;
不用多说,这个都知道,是内容超出容器高度以后,容器出现滚动条用的,这时候安卓和ios的差别性就来了,在安卓上你能够发现滚动没有任何异常,可是在ios上就会滑动异常卡顿,彻底划不动的感受;
因此加上了第二句-webkit-overflow-scrolling:touch;
这东西的功能很强大,能够解决大部分ios局部滚动不流畅的问题;web
那么这个-webkit-overflow-scrolling:touch;究竟是什么?chrome
一个只有 iOS 设备支持的非标准属性。苹果本身的解释:指定是否在 overflow: scroll 的元素中使用“原生”的滚动方式浏览器
他包含两个可选值:auto 和 touch安全
auto:就是普通的无惯性滚动效果(也就是上面说到的异常卡顿,彻底划不动的状况,这是默认值)
touch:原生的滚动效果。(也就是说能够得到跟原生app同样流畅的滚动效果);使用此效果会构造一个 stacking context !什么是 stacking context?这能够说是CSS里一个阴暗面,极其晦涩。我是没看明白ヾ(=・ω・=)o) 总之全部的坑都是由此而起!!微信
这个问题的缘由其实也是-webkit-overflow-scrolling形成的;app
**1, 在safari上,使用了-webkit-overflow-scrolling:touch以后,页面偶尔会卡住不动。
2, 在safari上,点击其余区域,再在滚动区域滑动,滚动条没法滚动的bug。
3, 经过动态添加内容撑开容器,结果根本不能滑动的bug。**
其中第一个问题主要是当滚动区域内容滚到顶或者滚到底就会出现此问题,当到顶和到底以后再滚动,这时候若是接着滚动的话,他就可能会连同整个页面一块儿卷动,这时候在滑动就会卡住(与其说是卡住更不如说是被body粘住...很难以形容 (〃´皿`)q);
第二个问题就是在滚动过程当中,若是点击其余地方,在回来滚动也会划不动
第三个问题我暂时没遇到
另外这个滚动我甚至感受还和手指滚动力度,动做幅度有关系哦...总之很奇怪!更加奇怪的是在百度上甚至很难找到对应的关键词条
补充一些其余资料
简单翻译就是:若是我在一个滚动div里面使用了-webkit-overflow-scrolling:touch,它能够得到堪比原生滚动通常的效果,可是,div它本身有时候会冻结(?)而且不会响应个人手指滑动,在2-3秒以后才能够再一次滚动(英语2级都没过的渣渣翻译ヾ(◍°∇°◍)ノ゙,可是这个状况确实跟我上面的问题极为类似);
而这个偶尔卡住的问题,解决方案网上众说纷纭,遇到了不少相同的说法,好比若是卡住不动的话,就加一个z-index,就能解决该问题的说法。
在试了不少次以后,这种说法没有一次解决过这个问题。这个说法可以传播出来,多是使用者当时在使用的时候遇到了-webkit-overflow-scrolling:touch点透或者层级的问题。因此该方案不具备适用性。
因此这个东西真的让我很苦恼了好久,以至于那段时间全部的滚动条不是经过body本身滚动,就是使用iScroll这样的库;
若是出现偶尔卡住不动的状况,那么在使用该属性的元素上不设置定位或者手动设置定位为static;
这样会解决部分由于定位(relative、fixed、absolute)致使的页面偶尔不能滚动的bug。
可是滑动到顶部继续手指往下滑,或者到底部继续往上滑,仍是会触发卡住的问题(实际上是整个页面上下回弹),说他算bug,其实就是ios8以上的特性,若是滚动区域大一点,用户不会以为这是bug,若是小了,用户会不知道发生了什么而卡住了。
附上原文地址:深刻研究-webkit-overflow-scrolling:touch及ios滚动
以前这个的确是发生了,在滚动过程中不会发生取值变化,只有在滚动结束时候发生一次,可是如今我居然没法重现这个bug了,此bug目前暂无解决办法...(TAT)...后续补上
ps: 这个问题产生的缘由仍是内核的问题,新版的微信浏览器已经修复了这个bug,其余的第三方浏览器也不会有这个问题,他们都已经转向了更为优秀的WKWebView,可是你在手机QQ上自带的那个浏览器上就会遇到这个问题,取不到scrollTop 的值;至少到我写这个附注的这一刻为止,这个问题尚未获得解决;
这个东西也有人管他叫作滚动穿透,在h5上还有一个点击穿透(点透)问题,这两个问题总结;滚动穿透基本表现为当在上层(z-index较大的)元素上滚动时,底层元素会跟着滚动,最多见在遮罩弹窗上滚动,body也会跟着滚;你能够在显示半透明蒙版时将 ul 的 -webkit-overflow-scrolling: touch 或 overflow: scroll 去掉,可是会形成屏幕明显的闪烁。若是给 body 的 touchmove事件 preventDefault() 能够防止触发滚动,可是是全部滚动区域都会失效.
说到底那么形成以上种种问题的缘由究竟是什么呢?有没有什么好的解决方案呢?
因为苹果公司对安全性等缘由的考虑,苹果公司静止第三方浏览器在 iOS 设备上使用本身的浏览器的内核,换句话说,使用本身内核的浏览器都被禁止上架 AppStore。各大厂商无奈,因而长久以来,包括 Chrome 在内的全部第三方浏览器,都只是使用 iOS 系统内置的浏览器控件包一层外壳,(这在国内被称为壳浏览器,其实国内大部分浏览器都是这样的,号称双核甚至多核浏览器的那些浏览器,他们的兼容模式其实就是使用的ie内核(trident),急速模式就是webkit内核,关于内核之战后面开一个闲谈)这个控件就是 UIWebView。这个 UIWebView 不只速度差,HTML5 支持率低,占用内存高,还有各类各样奇怪的问题。然而苹果公司却给本身的 Safari 浏览器开了后门。首先 Safari 使用的支持 JIT 编译的 JS 引擎内核 Nitro 比 UIWebView 里老旧的解释性 JavaScriptCore 内核速度搞数倍,而后 HTML5 支持度也比 UIWebView 高,还少了某些奇葩bug。长此以往就造成了 iOS 设备上 Safari 浏览器全面碾压其余第三方浏览器的现象。
在乔帮主撒手人寰不久以后,苹果公司口气终于松动,虽然没有放开第三方浏览器内核的限制,但把 Safari 的浏览器内核提取了出来开放第三方浏览器使用,那就是现在的 WKWebView(WK 即 Webkit 的缩写)。但因为 WKWebView 只支持 iOS8 以上系统,各大浏览器厂商并未马上跟进。直到最近的 iOS9 时代,Chrome 成为第一个吃螃蟹的 APP,使用了 WKWebView 内核。测试数据代表,使用 WKWebView 内核的 Chrome 浏览器在速度和 HTML5 支持率上已经与 Safari 浏览器不相上下。紧接着 Mozilla 公司宣布 Firefox 登陆 iOS 平台,使用的也是 WKWebView 内核(因而有了第一款基于 Webkit 内核的火狐浏览器 :)
不知苹果作了什么手脚,也许苹果的开发人员认为 WKWebView 的效能已经足以支撑在 scroll 事件中执行额外代码而不形成 UI 卡顿,总之在 WKWebView 内核中滚动能够正常触发 scroll 事件,固然也能正常得到 scrollTop 的值。可是滚动穿透的问题依然存在。
在经历了那么多问题以后,终于找到了一款优秀的插件better-scroll,最后这个问题终于获得解决;详情能够百度better-scroll
better-scroll的经常使用参数和方法
//一个简单的例子 <div class="wrapper"> //请注意检查这东西和.content的高度,假设划不动你能够看看他们的css是否是内外城高度错了 <div class="content"> content... </div> </div> <script> var wrapper=$('#wrapper); var myScroll=new BScroll(wrapper,{ //直接实例化就好,参数可根据实际状况或查看使用说明添加 HWCompositing:true, useTransition:false, // 防止iphone微信滑动卡顿 probeType: 3, click:true, wheel:false, snap:false, }); </script>
**
在使用bs的时候值得注意的几点
1,是假设在滚动区域里面夹杂了图片,那么可能会由于图片的加载问题致使betterscroll高度计算不正确,因此能够的话给图片绑定上一个onload事件,而后调用他的refresh();
<img onload="imgRefresh()"> imgRefresh(){ myScroll.refresh(); }
2,任何动态添加元素进去滚动区域的时候(比方append的时候),最好都调用一次refresh()方法,让他本身从新计算一次滚动距离,防止意外
3,scroll实例化时候的选择器问题,必定要保证惟一性 也就说加入你是用的是jquery的class选择器,好比class为wrap 那么必定要使用$('.wrap')[0]来确保惟一性;或者你可使用原生选择器方法 document.querySelector(selectors[, NSResolver]);
4,scroll滑动区域若是碰上了display:none; 那么极有可能会出现实例化了可是没法滚动的状况,由于display:none 的元素在页面上是没有宽高属性,只会获得0或者其余的什么稀奇古怪的值,因此插件只会拿到彻底错误的宽高数据,那么就没法正确实例化,
要解决这个问题的话就是用他提供的refresh()方法,你只须要在点击显示遮罩的时候手动refresh()就行了
var bsw=cbs(); //建立bs 实例 $('.showbs').click(function(event) { //点击显示bs 弹窗 $('.option-mask').show(); bsw.refresh(); //手动刷新,强制计算bs实例 });
隐藏的时候什么都不用管,普通hide()就好
5, 请注意内容的包裹元素和外层父元素的高度关系 实例化的那个dom元素的高度必定是固定的,并且必须小于内容的直系包裹元素,只有这样才能产生滚动落差,有时候你很容易实例化错误的dom对象;而后内容的直系包裹元素你不能有高度属性,他的高度就是里面内容高度;