1. 程式人生 > >網頁在Safari快速滾動和回彈的原理: -webkit-overflow-scrolling : touch;的實現

網頁在Safari快速滾動和回彈的原理: -webkit-overflow-scrolling : touch;的實現

現在很多for Mobile的HTML5網頁內都有快速滾動和回彈的效果,看上去和原生app的效率都有得一拼。

要實現這個效果很簡單,只需要加一行css程式碼即可:

-webkit-overflow-scrolling : touch;
可用以下網頁測試:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta charset="utf-8" />
        <title>scroll</title>
        <style type="text/css">
            .container {
                width : 300px;
                height : 50%;
                -webkit-box-sizing : border-box;
                position : relative;
                overflow-y : auto;
                background-color : cyan;
                -webkit-overflow-scrolling : touch;  /* liuhx:可以把這整行註釋掉對比差別 */
            }
            ul {
                height: 50px;
            }
        </style>
    </head>
<body>
    <div align="center">
        <nav class="container">
            <ul>1</ul>
            <ul>2</ul>
            <ul>3</ul>
            <ul>4</ul>
            <ul>5</ul>
            <ul>6</ul>
            <ul>7</ul>
            <ul>8</ul>
            <ul>9</ul>
            <ul>10</ul>
            <ul>11</ul>
            <ul>12</ul>
            <ul>13</ul>
            <ul>14</ul>
            <ul>15</ul>
            <ul>16</ul>
            <ul>17</ul>
            <ul>18</ul>
            <ul>19</ul>
            <ul>20</ul>
        </nav>
    </div>
</body>
</html>
可以用手指滑動中間的藍色區域,會發現回彈效果以及滾動得很快:


(點選圖片檢視大圖)
如果把-webkit-overflow-scrolling那行註釋掉,就會發現滾動得很慢。

實際上,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

這個巨集裡。

從SVN log看,在WebKit 108400版本左右才支援,所以iOS Safari應該是需要5.0。Android只在4.0以上支援。

從前端開發的角度講,只需要知道CSS的屬性-webkit-overflow-scrolling是真的建立了帶有硬體加速的系統級控制元件,所以效率很高。但是這相對是耗更多記憶體的,最好在產生了非常大面積的overflow時才應用。

相關推薦

網頁Safari快速滾動原理 -webkit-overflow-scrolling : touch;的實現

現在很多for Mobile的HTML5網頁內都有快速滾動和回彈的效果,看上去和原生app的效率都有得一拼。 要實現這個效果很簡單,只需要加一行css程式碼即可: -webkit-overflow-scrolling : touch;可用以下網頁測試: <!DO

禁止UIWebView滾動方法

轉自 http://blog.csdn.net/jinglijun/article/details/8333889 精緻uiwebview滾動和反彈的方法其實也很簡單,但是有個問題是,在html中又滾動的檢視的話,也會被禁止,要用css 來 在html自己實現了。 我個人

轉載深入研究-webkit-overflow-scrolling:touch及ios滾動

深入研究-webkit-overflow-scrolling:touch及ios滾動 原文章連結:https://www.cnblogs.com/xiahj/p/8036419.html 目錄 -webkit-overflow-scrolling:touch是什麼? 解決s

-webkit-overflow-scrolling:touch;在本身沒有滾動,動態加入內容撐大後不滾動的bug

使用weui 1.0開發時,專案列表的div在ajax填充後,頁面無法滾動,真的傷腦筋啊!研究了好久終於解決了 When working with the overflow: scroll; attribute, the -webkit-overflow-scrolli

ios滾動不流暢問題之 -webkit-overflow-scrolling:touch

1. -webkit-overflow-scrolling:touch是什麼?MDN上是這樣定義的:-webkit-overflow-scrolling 屬性控制元素在移動裝置上是否使用滾動回彈效果.auto: 使用普通滾動, 當手指從觸控式螢幕上移開,滾動會立即停止。tou

-webkit-overflow-scrolling滾動效果.

插件 列表 卡住 快的 優雅 css 移動設備 分享 兼容性 參考來源:https://developer.mozilla.org/zh-CN/docs/Web/CSS/-webkit-overflow-scrolling      https://www.w3cways.

AppBarLayout快速滑動導致的解決方案CollapsingToolbarLayout

在26版本的sdk上,谷歌解決了之前存在已久的一個問題:AppBarLayout、CollapsingToolbarLayout和RecyclerView共存時,無法通過fling快速展開AppBarLayout 但是隨之而來的是一個新問題,當快速上下滾動,最後回到頂部時,AppBarLayout會出現回

JdbcTemplate 使用了模版模式撥函式

1.T execute(ConnectionCallback<T> action) 主要結構 使用了ConnectionCallback中的方法作為回撥方法 public <T> T execute(ConnectionCallback

-webkit-overflow-scrolling解決移動端iOS滾動卡頓現象

css3中-webkit-overflow-scrolling使用方法 -webkit-overflow-scrolling: touch; //有回彈效果 -webkit-overflow-scrolling: auto; //滑到哪停到哪 實現滾動回彈效果的頁面佈局

Android推送的核心原理長連線的簡單實現

實際需求 移動端需要實時的獲取伺服器的資料 解決方案 輪詢方式:應用程式開啟定時的輪詢,不停的向伺服器請求資料。 SMS push:傳送二進位制簡訊到移動終端,來達到通知終端的目的。客戶端攔截這類簡訊,然後採取相應的操作 持久連線方式:應用程式與伺服

iOS原生流暢滾動屬性overflow-scrolling:touch

屬性。 china html over https 開發 效果 rdquo pan 在移動端中,現在使用系統的滾動條已經體驗很好了,但發現對某個元素使用了overflow:scroll時,如果有滾動條,在裏面滑動內容時會卡頓不流暢。· 今天推薦的這個CSS屬

ios 下防止整個網頁滑動(阻尼 . 瞞天過海,騙IOS,把阻尼限制在滾動區div內

list ont 16px 一點 width sta 常見 沒有 手機app 下面是一個手機APP頁面,分成上中下三部分,最上面和最下面是固定的,中間可以滾動。這是常見的APP布局方式。 <style> .box{ overflow: auto; -

移動端出層平滑滾動fix定位的沖突

-s 解決 branch sla 3D andro fixed lin 滾動 #branch-list{ overflow: scroll; -webkit-overflow-scrolling: touch;/* ios 平滑滾動*/ overflow-sc

簡述原理CDN常見多級快取

一、CDN回源 1、回源原理 源站內容有更新的時候,源站主動把內容推送到CDN節點。 常規的CDN都是回源的。即:當有使用者訪問某一個URL的時候,如果被解析到的那個CDN節點沒有快取響應的內容,或者是快取已經到期,就會回源站去獲取。如果沒有人訪問,那麼CDN節點不會主動去

移動端導航過多,點擊導航左右滾動

image 滾動 元素 order 100% 效果 over geturl isp 移動端導航過多,點擊導航左右滾動回彈 移動端項目導航欄目很多,需要左右滑動,前面文章,已經實現,跳轉頁面也實現了,現在問題是,當點擊後面的導航欄目時候,聚焦當前的時候, 需要給當前導航添加一

java原理,以及CallableFutureTask通過撥機制建立可監控的執行緒

回撥的概念會JS的人應該都能理解。 回撥分非同步回撥,同步回撥。但是同步回撥其實沒什麼意義。都同步了,那麼直接等那邊執行完了,這邊再執行就可以了,沒必要通過回撥。我們說的回撥主要是講非同步回撥。用於兩個執行緒甚至兩個系統之間互動呼叫。 例如我在A類的方法funa()中,要呼叫B類的方法fun

css實現返回首部滾動監聽的原理

 在頁面中實現返回首部  原理將<a>連線到頂部的其中一個標籤 當點選這個連結時  可以實現返回頂部 js 在裡面實現返回圖示的出現 注意的是實現的邏輯為  考察滾動條距離頂部的距離 方法

mui之上拉重新整理mui-content結合解決ios上拉不的bug

var globalphone; mui.init({ swipeBack: true, //啟用右滑關閉功能 pullRefresh: { contai

listview實現自動向上滾動快速滾動滾動條的一些設定

1 android:windowSoftInputMode=”adjustResize” 也無法解決問題。 通過部落格,在listview中新增以下三個屬性,可行: 繼承於view and

具有效果的RecyclerView,RecyclerView外層可滾動容器

    一個具有回彈效果的RecyclerView,本文通過實現RecyclerView外層的容器的上下滑動達到了回彈的效果,在整個滑動的事件分發機制中,外層容器的事件攔截機制進行判斷是否攔截事件,判斷標準為RecyclerView是否滾動到了第一個item或者最後一個i