滑動,對於移動端來講多麼簡單的一個動做,上下動動手指頭唄,就比如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對象;而後內容的直系包裹元素你不能有高度屬性,他的高度就是裏面內容高度;