CSS3中-webkit-overflow-scrolling: touch 的使用方法详解

我们一起来看一篇关于 css中-webkit-overflow-scrolling: touch 手动改变 scrollTop 导致的 bug 及解决方案,希望此解决方案能够帮助到各位同学。

关于-webkit-overflow-scrolling,看看相关API,主要用来设置在IOS浏览器的容器内滚动是否开启惯性和回弹的。

所以,一般情况都是设置其值为touch的

-webkit-overflow-scrolling: touch

但是,这一次遇到一个BUG。

我的需求是需要手动设置滚动高度的,js代码是

el.scrollTop = 500;

此时,我发现在IOS环境下,每次手动改变scrollTop后整个容器变成空白,但手指触摸一下内容就出来了,scrollTop是成功改变了的,只是内容绘制出错。(这里我个人判断是浏览器底层的问题,因为安卓不存在这问题)

我通过用延迟加载,延迟设置滚动,或者是手动改变容器中的内容来强制重绘,可惜都不起作用,最终找到问题出在-webkit-overflow-scrolling: touch,因为当我把值设置为auto时BUG不存在。

思路出来了,在手动设置scrollTop前,先关闭惯性滚动,待设置完成后重新开启即可。

贴上解决代码:

el.WebKitOverflowScrolling = 'auto';
el.scrollTop = 500;
el.WebKitOverflowScrolling = 'touch';

查了一下网上的资料,H5端代码就不再敷述了,看一下Native处理

-webkit-overflow-scrolling: touch 的流程如下:

实际上,Safari真的用了原生控件来实现,对于有-webkit-overflow-scrolling的网页,会创建一个UIScrollView,提供子layer给渲染模块使用

要实现这个效果很简单,只需要加一行css代码即可:

[css] view plain copy 在CODE上查看代码片派生到我的代码片
-webkit-overflow-scrolling : touch; 
可用以下网页测试:
[html] view plain copy 在CODE上查看代码片派生到我的代码片
<!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给渲染模块使用。创建时的堆栈如下:

[plain] view plain copy 在CODE上查看代码片派生到我的代码片
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,声明为:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
@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的声明为:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
@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时才应用。

时间: 2024-09-10 19:36:17

CSS3中-webkit-overflow-scrolling: touch 的使用方法详解的相关文章

Android中gson、jsonobject解析JSON的方法详解_Android

JSON的定义: 一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持),从而可以在不同平台间进行数据交换.JSON采用兼容性很高的文本格式,同时也具备类似于C语言体系的行为. JSON对象: JSON中对象(Object)以"{"开始, 以"}"结束. 对象中的每一个item都是一个key-value对, 表现为"key:value"的形式, ke

Android中gson、jsonobject解析JSON的方法详解

JSON的定义: 一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持),从而可以在不同平台间进行数据交换.JSON采用兼容性很高的文本格式,同时也具备类似于C语言体系的行为. JSON对象: JSON中对象(Object)以"{"开始, 以"}"结束. 对象中的每一个item都是一个key-value对, 表现为"key:value"的形式, ke

jQuery中Ajax的get、post等方法详解

 前面我们讲述了jQuery中ajax的load()方法,小伙伴们反应非常好,今天我们就来讲解下jQuery中Ajax的get.post等方法,希望大家同样能够喜欢.     load()方法通常用来从Web服务器上获取静态的数据文件,然而这并不能体现ajax的全部价值. 在项目中,如果需要传递一些参数给服务器中的页面,那么可以使用$.get()或者$.post()方法(或者是$.ajax()方法) $.get()方法使用GET方式来进行异步请求.结构为:$.get(url [, data] [

linux系统中VNC远程桌面安装和配置方法详解

具体方法 1.检查linux系统是否安装VNC命令rpm -q vnc-server 如果没有安装则使用yum install vnc vnc-server 2.启动vnc服务  代码如下 复制代码 vncserver You will require a password to access your desktops. Password: Verify: 输入两次密码,这个就是你远程登陆时所需要的密码. 3.修改配置文件,root账户下  代码如下 复制代码 vi /etc/sysconfi

thinkPHP中钩子的两种配置调用方法详解_php实例

本文实例讲述了thinkPHP中钩子的两种配置调用方法.分享给大家供大家参考,具体如下: thinkphp的钩子行为类是一个比较难以理解的问题,网上有很多写thinkphp钩子类的文章,我也是根据网上的文章来设置thinkphp的钩子行为的,但根据这些网上的文章,我在设置的过程中,尝试了十几次都没有成功,不过,我还是没有放弃,最后还是在一边调节细节,一边试验的过程中实现了钩子行为的设置.下面是我个人的设置经验,在这里跟大家分享一下. 个人做了两种设置,都试验成功了,一个简单点,在thinkphp

Java多线程编程中使用Condition类操作锁的方法详解_java

Condition的作用是对锁进行更精确的控制.Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signalAll()相当于Object的notifyAll()方法.不同的是,Object中的wait(),notify(),notifyAll()方法是和"同步锁"(synchronized关键字)捆绑使用的:而Condition是需要与"互斥

thinkPHP中钩子的两种配置调用方法详解

本文实例讲述了thinkPHP中钩子的两种配置调用方法.分享给大家供大家参考,具体如下: thinkphp的钩子行为类是一个比较难以理解的问题,网上有很多写thinkphp钩子类的文章,我也是根据网上的文章来设置thinkphp的钩子行为的,但根据这些网上的文章,我在设置的过程中,尝试了十几次都没有成功,不过,我还是没有放弃,最后还是在一边调节细节,一边试验的过程中实现了钩子行为的设置.下面是我个人的设置经验,在这里跟大家分享一下. 个人做了两种设置,都试验成功了,一个简单点,在thinkphp

Android studio中生成引用.aar和.jar的方法详解_Android

在Android Studio中对一个自己库进行生成操作时将会同时生成*.jar与*.aar文件. 分别存储位置:      *.jar:库 /build/intermediates/bundles/debug(release)/classes.jar      *.aar:库 /build/outputs/aar/libraryname.aar .jar 与 .aar的区别 从名称上来讲,一个是java application resource:一个是android application r

C#中委托(Delegates)的使用方法详解_C#教程

1. 委托是什么? 其实,我一直思考如何讲解委托,才能把委托说得更透彻.说实话,每个人都委托都有不同的见解,因为看问题的角度不同.个人认为,可以从以下2点来理解:  (1) 从数据结构来讲,委托是和类一样是一种用户自定义类型.  (2) 从设计模式来讲,委托(类)提供了方法(对象)的抽象. 既然委托是一种类型,那么它存储的是什么数据? 我们知道,委托是方法的抽象,它存储的就是一系列具有相同签名和返回回类型的方法的地址.调用委托的时候,委托包含的所有方法将被执行. 2. 委托类型的定义 委托是类型