Viewport那些事(四)
2013-05-05 11:44
330 查看
meta viewport
为了更好地方便网页作者在移动浏览器上设置合适自己网页的viewport,Apple在meta标签中引入了viewport属性,相关的介绍可以看这里:《Using the viewport》
http://developer.apple.com/library/ios/#documentation/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html
scale
这里缩放比例指的是设备像素和CSS像素之间的比例,即可以认为是device-width/height和visual viewport(可以通过window.innerWidth/Height获取)之间的比例。
旋转屏幕
Safari旋转屏幕是保持visual viewport的宽度不变,除非超出最大/最小缩放比例,所以旋转屏幕后缩放比例会发生变化。
Viewport的默认值(IOS)
首先来看看width的默认值,前面和Apple的文档中都有提到viewport的默认值中width为980px,但是当initial-scale被设置为1.0的时候,Safari会认为width的值为device-width。所以如你想设置initial-scale为1.0并且viewport的宽度为980px时,你需要同时设置这两个属性,详见《Using the viewport》。
其他属性的默认值文档中虽然没有提到,但是很容易试验出来。
minimum-scale,它的值是根据排版出来的document大小来计算,Safari会取参考值0.25,device-width/document.width和device-height/document.heght的最大值,可以看出Safari的设计是想保证visual viewport刚好包含文档的整个宽度或者刚好包含文档的整个高度。
maxmum-scale,如果没有指定,Safari会取maxmum-scale为5。
initial-scale,如果没有指定,Safari会取initial-scale = minimum-scale。
基于以上这些结论,可以比较容易地知道不同网页在不同meta viewport设置下的layout viewport和初始的visual viewport,我们还是以(三)中的那个页面为例来说明,没有设置viewport属性并且文档高度足够大,如果页面中存在比较大的overflow元素,例如width:2000px,那么文档的宽度document.width就是2000,Safari Mobile根据以上规则计算出的minimum-scale和initial-scale就是document.width/device-width,所以初始打开页面会是这样:
如果没有overflow元素,document.width就是viewport的大小980,初始打开页面就会是这样:
如果 网页通过javascript动态调整页面的宽度或高度,那么就有可能导致Safari Mobile打开页面后计算出的minimum-scale和initial-scale不断变化而发生抖动,在用户进行了一次缩放或者旋屏之后抖动停止。
initial-scale对width的影响
如果没有设置width而设置了initial-scale,那么width = device-width / initial-scale
如果设置了width并且设置了initial-scale,那么width为device-width / initial-scale和设置的width间的最大值
document大小对minimum-scale的影响
即使网页作者指定了minimum-scale的值,它也会根据排版出来的document大小来调整,最终的值为minimum-scale,document.width/device-width和document.heght/device-height三者之间的最大值。
Safari中Viewport的处理流程
viewport相关的数据结构
viewport参数在Document中保存的结构如下所示:
结构中每一个值都对应这meta标签中viewport的属性值,默认值都是ValueAuto(-1)。
触发Viewport更新的时机
在WebKit源码中,触发viewport更新的时机只有两处,分别是在加载第一次接收到数据并且Document创建之后和Meta标签处理时解析到viewport属性时,相应的函数调用关系图如下:
在Document创建之后更新viewport时ViewportArguments为默认值ValueAuto。
viewportArguments的处理
线程分工
在对Viewport的处理中,内核线程仅完成viewport的解析步骤就将viewport参数抛给主线程来处理。
主线程会完成viewport的计算和处理工作。除了内核线程抛转来的viewport消息,一些其它情况也会触发主线程中viewport的计算步骤。
在WebKit源码中,WebCore只解析viewport的属性并不处理ViewportArguments(通过Document::processArguments函数解析Viewport参数),而是将其交给ChromeClient来处理,对应的函数调用关系图如下:
在Safari的ChromeClientIOS::dispatchViewportPropertiesDidChange函数中会调用Frame::dictionaryForViewportArguments函数将Viewport参数封装成NSDictionary的形式传递给主线程来处理。
主线程在收到消息后会调用UIWebDocumentView的viewportConfigurationsDidChange函数来处理viewport参数。
根据前面的讨论,viewport中最小缩放比例会根据document的大小进行调整,而document的大小在动态网页中经常会发生变化,这是viewport就需要重新计算。所以主线程处理Viewport参数的函数viewportConfigurationsDidChange除了被内核线程Document::updateViewportArguments抛转的消息触发外,还有可能在文档大小发生变化时被调用。
另外,观察Safari中Viewport计算函数的调用栈,还有如下一些情况也可能会触发viewport的重新计算。
为了更好地方便网页作者在移动浏览器上设置合适自己网页的viewport,Apple在meta标签中引入了viewport属性,相关的介绍可以看这里:《Using the viewport》
http://developer.apple.com/library/ios/#documentation/AppleApplications/Reference/SafariWebContent/UsingtheViewport/UsingtheViewport.html
scale
这里缩放比例指的是设备像素和CSS像素之间的比例,即可以认为是device-width/height和visual viewport(可以通过window.innerWidth/Height获取)之间的比例。
旋转屏幕
Safari旋转屏幕是保持visual viewport的宽度不变,除非超出最大/最小缩放比例,所以旋转屏幕后缩放比例会发生变化。
Viewport的默认值(IOS)
首先来看看width的默认值,前面和Apple的文档中都有提到viewport的默认值中width为980px,但是当initial-scale被设置为1.0的时候,Safari会认为width的值为device-width。所以如你想设置initial-scale为1.0并且viewport的宽度为980px时,你需要同时设置这两个属性,详见《Using the viewport》。
其他属性的默认值文档中虽然没有提到,但是很容易试验出来。
minimum-scale,它的值是根据排版出来的document大小来计算,Safari会取参考值0.25,device-width/document.width和device-height/document.heght的最大值,可以看出Safari的设计是想保证visual viewport刚好包含文档的整个宽度或者刚好包含文档的整个高度。
maxmum-scale,如果没有指定,Safari会取maxmum-scale为5。
initial-scale,如果没有指定,Safari会取initial-scale = minimum-scale。
基于以上这些结论,可以比较容易地知道不同网页在不同meta viewport设置下的layout viewport和初始的visual viewport,我们还是以(三)中的那个页面为例来说明,没有设置viewport属性并且文档高度足够大,如果页面中存在比较大的overflow元素,例如width:2000px,那么文档的宽度document.width就是2000,Safari Mobile根据以上规则计算出的minimum-scale和initial-scale就是document.width/device-width,所以初始打开页面会是这样:
如果没有overflow元素,document.width就是viewport的大小980,初始打开页面就会是这样:
如果 网页通过javascript动态调整页面的宽度或高度,那么就有可能导致Safari Mobile打开页面后计算出的minimum-scale和initial-scale不断变化而发生抖动,在用户进行了一次缩放或者旋屏之后抖动停止。
initial-scale对width的影响
如果没有设置width而设置了initial-scale,那么width = device-width / initial-scale
如果设置了width并且设置了initial-scale,那么width为device-width / initial-scale和设置的width间的最大值
document大小对minimum-scale的影响
即使网页作者指定了minimum-scale的值,它也会根据排版出来的document大小来调整,最终的值为minimum-scale,document.width/device-width和document.heght/device-height三者之间的最大值。
Safari中Viewport的处理流程
viewport相关的数据结构
viewport参数在Document中保存的结构如下所示:
struct ViewportArguments { enum { ValueAuto = -1, ValueDeviceWidth = -2, ValueDeviceHeight = -3, ValuePortrait = -4, ValueLandscape = -5 }; float width; float minWidth; float maxWidth; float height; float minHeight; float maxHeight; float zoom; float minZoom; float maxZoom; float userZoom; float orientation; };
结构中每一个值都对应这meta标签中viewport的属性值,默认值都是ValueAuto(-1)。
触发Viewport更新的时机
在WebKit源码中,触发viewport更新的时机只有两处,分别是在加载第一次接收到数据并且Document创建之后和Meta标签处理时解析到viewport属性时,相应的函数调用关系图如下:
在Document创建之后更新viewport时ViewportArguments为默认值ValueAuto。
viewportArguments的处理
线程分工
在对Viewport的处理中,内核线程仅完成viewport的解析步骤就将viewport参数抛给主线程来处理。
主线程会完成viewport的计算和处理工作。除了内核线程抛转来的viewport消息,一些其它情况也会触发主线程中viewport的计算步骤。
在WebKit源码中,WebCore只解析viewport的属性并不处理ViewportArguments(通过Document::processArguments函数解析Viewport参数),而是将其交给ChromeClient来处理,对应的函数调用关系图如下:
在Safari的ChromeClientIOS::dispatchViewportPropertiesDidChange函数中会调用Frame::dictionaryForViewportArguments函数将Viewport参数封装成NSDictionary的形式传递给主线程来处理。
NSDictionary* Frame::dictionaryForViewportArguments(const ViewportArguments& arguments) const { return [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:NSFloatValue(arguments.initialScale), NSFloatValue(arguments.minimumScale), NSFloatValue(arguments.maximumScale), NSFloatValue(arguments.userScalable), NSFloatValue(arguments.width), NSFloatValue(arguments.height), nil] forKeys:[NSArray arrayWithObjects:@"initial-scale", @"minimum-scale", @"maximum-scale", @"user-scalable", @"width", @"height", nil]]; }
主线程在收到消息后会调用UIWebDocumentView的viewportConfigurationsDidChange函数来处理viewport参数。
根据前面的讨论,viewport中最小缩放比例会根据document的大小进行调整,而document的大小在动态网页中经常会发生变化,这是viewport就需要重新计算。所以主线程处理Viewport参数的函数viewportConfigurationsDidChange除了被内核线程Document::updateViewportArguments抛转的消息触发外,还有可能在文档大小发生变化时被调用。
另外,观察Safari中Viewport计算函数的调用栈,还有如下一些情况也可能会触发viewport的重新计算。
相关文章推荐
- Viewport那些事(一)
- Viewport那些事(二)
- Viewport那些事(三)
- Android开发环境搭建那些事
- 关于内存对齐的那些事
- HTTPS那些事(一)HTTPS原理
- Android fillViewPort属性用法
- Spring2.5那些事之基于AOP的方法级注解式日志配置
- 解决PhoneGap不支持viewport的几种方法
- ios tableView那些事 (十)设置 tableview 的分割线
- 你所不知道的html5与html中的那些事(三)
- Bitmap那些事之内存占用计算和加载注意事项
- opencv中SVM的那些事
- iphone,ipad,关于icon图标的那些事
- Kafka文件存储机制那些事
- 你所不知道的html5与html中的那些事(五)——web图像
- C语言的那些事
- Java那些事之正则表达式(http://blog.csdn.net/cping1982/article/details/1900808)
- 【经验】谈谈办证的那些事,献给那些即将毕业、或孩子上学等朋友(转)
- 明朝那些事2