解決頁面使用overflow: scroll在iOS上滑動卡頓的問題

一:Lying人生感悟(可忽略)html

         摩西奶奶曾經說過:世界上,最公平和最不公平的,都是時間。別人偷不走它。而你也留不住它。你擁有它,卻不能改變它。光陰裏的艱難或是快樂,它都一一帶走。身處其中的你我,年輕或是衰老,所能作的,就是充分去享用它,享受每個生命時期,收藏每個年齡段帶給你的感動與美好。前端

         是的,這句話我也曾經在某個使人刻骨銘心的夜晚對一我的說過。過去了的事情再說起不免讓人有些懷念。既然走不出來又何須再強求本身走出來。因此讓該來的到來,讓不應走的別走,珍惜所擁有的一切期許是最好的選擇……node

二:回到正題(待細看)android

  故事背景:最近的一次開發中,使用到了overflow:scroll 屬性來滑動div。信心滿滿的覺得不會出現任何問題,看來仍是太清高自傲了,因而寫下這篇隨筆特此總結一番。ios

  若是你對某個div或模塊使用了overflow: scroll屬性,在iOS系統的手機上瀏覽時,則會出現明顯的卡頓現象。可是在android系統的手機上則不會出現該問題。你們不妨能夠分別使用IOS和Android系統的手機瀏覽如下連接或掃描二維碼後滑動文字區域查看該效果(重點是記住iPhone瀏覽時的效果,方便瀏覽後文):http://geek100.com/demo/os.html.web

 

  表示很奇怪會產生這樣的差別,因而卸下行囊、放下面包、拿出電腦、插上網線、雙擊chrome、在輸入欄中默默地敲上baidu.com...大百度(我更習慣性的稱做爲大敗毒,由於它幾乎構成了我學習、工做、生活的所有)。經過一個早上的爬蟲搜索和與前端開發高手的技術探討得知如下代碼可解決這種卡頓的問題:chrome

-webkit-overflow-scrolling: touch;app

  嗯,此次收拾好心情、重拾以前唾手可棄的信心(不是節操哦)、利用PP助手謹小慎微地把文件拖入iPhone手機中、當心翼翼地點開頁面、手指輕輕在屏幕上滑動...哇哦,果真滑動流暢了誒。來吧!朋友!不妨拿出IPhone一塊兒感覺這激動的時刻。連接:http://geek100.com/demo/ost.htmloop

 

 

  聽說是由於這行代碼啓用了硬件加速特性,因此滑動很流暢。可是這個屬性也會相對耗費更多內存。在流暢的滑動效果和耗費內存之間,我選擇了前者。學習

  後來深刻研究了一下該屬性。具體深刻點以下:

  實際上,Safari真的用了原生控件來實現,對於有-webkit-overflow-scrolling的網頁,會建立一個UIScrollView,提供子layer給渲染模塊使用。建立時的堆棧以下:

 

Thread 1, Queue : com.apple.main-thread #0 0x00086723 in -[UIScrollView initWithFrame:] () #1 0x004ec3bd in -[UIWebOverflowScrollView initWithLayer:node:webDocumentView:] () #2 0x001f1769 in -[UIWebDocumentView webView:didCreateOrUpdateScrollingLayer:withContentsLayer:scrollSize:forNode:allowHorizontalScrollbar:allowVerticalScrollbar:] () #3 0x01d571bd in __invoking___ () #4 0x01d570d6 in -[NSInvocation invoke] () #5 0x01d5724a in -[NSInvocation invokeWithTarget:] () #6 0x027fb6a1 in -[_WebSafeForwarder forwardInvocation:] () #7 0x027fb8ab in __44-[_WebSafeAsyncForwarder forwardInvocation:]_block_invoke_0 () #8 0x04ac753f in _dispatch_call_block_and_release () #9 0x04ad9014 in _dispatch_client_callout () #10 0x04ac97d5 in _dispatch_main_queue_callback_4CF () #11 0x01d09af5 in __CFRunLoopRun () #12 0x01d08f44 in CFRunLoopRunSpecific () #13 0x01d08e1b in CFRunLoopRunInMode () #14 0x01cbd7e3 in GSEventRunModal () #15 0x01cbd668 in GSEventRun () #16 0x00032ffc in UIApplicationMain () #17 0x00002ae2 in main at /Users/liuhx/Desktop/UIWebView_Research/WebViewResearch/main.mm:16

 

  實際建立的是UIWebOverflowScrollView,它繼承自UIScrollView,聲明爲:

 

@class DOMNode, UIWebDocumentView, UIWebOverflowContentView, UIWebOverflowScrollListener; @interface UIWebOverflowScrollView : UIScrollView { UIWebDocumentView *_webDocumentView; UIWebOverflowScrollListener *_scrollListener; UIWebOverflowContentView *_overflowContentView; DOMNode *_node; BOOL _beingRemoved; } @property(nonatomic, getter=isBeingRemoved) BOOL beingRemoved; // @synthesize beingRemoved=_beingRemoved; @property(retain, nonatomic) DOMNode *node; // @synthesize node=_node; @property(retain, nonatomic) UIWebOverflowContentView *overflowContentView; // @synthesize overflowContentView=_overflowContentView; @property(retain, nonatomic) UIWebOverflowScrollListener *scrollListener; // @synthesize scrollListener=_scrollListener; @property(nonatomic) UIWebDocumentView *webDocumentView; // @synthesize webDocumentView=_webDocumentView; - (void)setContentOffset:(struct CGPoint)arg1; - (void)_replaceLayer:(id)arg1; - (void)prepareForRemoval; - (void)fixUpViewAfterInsertion; - (id)superview; - (void)dealloc; - (id)initWithLayer:(id)arg1 node:(id)arg2 webDocumentView:(id)arg3; @end

 

  其還有一個子View做爲ContentView,是給WebCore真正用做渲染overflow型內容的layer的容器。UIWebOverflowContentView的聲明爲:

 

@interface UIWebOverflowContentView : UIView { } - (void)_setCachedSubviews:(id)arg1; - (void)_replaceLayer:(id)arg1; - (void)fixUpViewAfterInsertion; - (id)superview; - (id)initWithLayer:(id)arg1; @end

 

  再往底層跟,都是CALayer的操做。以上兩個類都是UIKit層的實現,須要WebCore有硬件加速的支持纔有實際意義,相關的邏輯被包含在ACCELERATED_COMPOSITING這個宏裏。

 

  原理說了一大堆,我表示一句也沒看明白。不過呢,做爲知識的分享者就應該要時時刻刻以最簡單明瞭的說法闡述問題,因此總結如下幾點供你們參考:

    1. 從SVN log看,在WebKit 108400版本左右才支持,因此iOS Safari應該是須要5.0。Android則是在4.0以上支持。
    2. 從前端開發的角度講,只須要知道CSS的屬性-webkit-overflow-scrolling是真的建立了帶有硬件加速的系統級控件,因此效率很高。
    3. 從實際開發的角度講,採用這樣的作法相對是耗更多內存的,最好是在產生了很是大面積的overflow時才應用。

三:補充內容(待注意)

  1. 上述所說的方法的確能夠解決ios5.0、android4.0之後系統的滑動卡頓問題,不過呢在這還能夠爲你們推薦一些相關插件:iScroll(這裏是iScroll插件的中文地址)、jRoll(中文名:酸蘿蔔) 。
  2. 關於掌握更多的解決方案或者經驗的朋友不妨在評論下方留言吧。關於閱讀本篇文章的讀者也歡迎大家在評論版裏對文章以及本人作出及時的評價與建議。讓咱們共同奮進!!!在這向大家表示感謝。
  3. 在這向文中所提到的前端高人表示真誠感謝。謝謝前輩的耐心解答以及給予的寶貴經驗。同時也感謝前輩在我工做之餘的時間裏化做暗夜中的一盞明燈,照亮我前行的方向。
  4. 在這向你們保證該隨筆中的任何一條連接都通過嚴格的篩選和把關。100%保證無毒無公害。用伊利純牛奶的廣告語改編後來講則是:百次驗證信賴,見證連接品質!(廣告:本隨筆由好喝的不要不要的伊利純牛奶贊助支持......連接:https://yili.tmall.com/search.htm)
相關文章
相關標籤/搜索