百分百源码网-让建站变得如此简单! 登录 注册 签到领金币!

主页 | 如何升级VIP | TAG标签

当前位置: 主页>网站教程>CSS教程> CSS3中-webkit-overflow-scrolling: touch 的使用方法详解
分享文章到:

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

发布时间:01/15 来源: 浏览: 关键词:
CSS3 的 -webkit-overflow-scrolling: touch 可以让页面在Native端滚动时模拟原生的弹性滚动效果,下面我们来看看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时才应用。

打赏

打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

百分百源码网 建议打赏1~10元,土豪随意,感谢您的阅读!

共有9人阅读,期待你的评论!发表评论
昵称: 网址: 验证码: 点击我更换图片
最新评论

本文标签

广告赞助

能出一分力是一分吧!

订阅获得更多模板

本文标签

广告赞助

订阅获得更多模板