移动端各终端的适配问题研究--关于viewport

概念理解

  • css像素与设备像素 
    设备像素是我们直观看到的像素。这些像素为你所使用的各种设备都提供了正规的分辨率。来看一个栗子

    .test{ 
    width:100px; 
    height:100px; 
    background-color:#2CDD53; 
    //zoom:200%; 

    给div设置一个的样式如上,当只设置宽高时,在普通的浏览器上显示的div宽高和设置的宽高时相同的,即css像素等于设备像素。当为div设置zoom放大后,div的css像素不变,但是div占据的设备宽高为200*200。所以,当对元素或者页面进行缩放时,设备像素和css像素是不同的。在缩放比为100%的情况下(zoom为1),一个css像素完全等一一个设备像素

    • 屏幕尺寸 
      可以通过screen.width/height获取。它们包括用户屏幕的整个宽度和高度,它们的尺寸以设备像素度量的,所以一个设备的宽度和高度是永远不会变的。它们是显示器的属性,而不是浏览器的
  • 窗口尺寸 
    窗口尺寸是浏览器窗口的整体大小(包括滚动条),是通过css像素度量的,可以通过window.innerWidth/window.innerHeight获得。它告诉开发人员有多少空间可以用来做css布局。当用户放大的时候,这个值会减小。所以如果用户进行放大操作,在窗口中能获取的空间将会变小,window.innerWidth/window.innerHeight的值也变小。
  • 滚动距离 
    window.pageXOffset和window.pageYOffset包含了文档水平和垂直方向的滚动距离。这个属性也是以css像素进行度量的。

视图(viewport)

视图的功能是用来约束网站中最顶级包含块元素html的 
当使用流式布局对网页中元素大小百分比表示时,我们知道他是以父元素宽度来计算实际宽度的。但是body的大小如何定义的呢。body是按照html元素的宽度定义的。在桌面环境下而html的宽度是和浏览器窗口的宽度是一样的。 
这里写图片描述 
而这样就会出现流式布局中常见的问题。在项目中设置导航栏的宽度为100%并设置背景色,由于其他元素宽度的原因,当缩小浏览器的宽度时会出现水平轮动条。当向右拉轮动条的时候会发现右侧导航栏为空白。其主要原因就是导航栏的宽度等于视口的宽度,当视口宽度发生变化,导航栏的宽度也发生变化,就可能导致导航栏显示不完全。 
如何度量viewport 
document.documentElement.clientWidth/clientHeight可以度量viewport的尺寸。这里需要说明一下window.innerWidth和window.innerHeight的区别:document.documentElement.clientWidth计算的宽度不算滚动条的宽度,而window.innerWidth的宽度将滚动条计算在内。 
如何度量html元素 
document.documentElement.offsetWidth/offsetHeight可以获得html元素的 
事件中的坐标 
当一个鼠标事件发生时,event事件中提供了坐标的相关信息 
pageX/Y提供了相对于html元素的以css像素度量的坐标 
clientX/Y提供了相对于viewport的以css相对度量的坐标。 
screenX/Y提供了相对于屏幕的以设备像素进行度量的坐标。

移动端的viewport

不同于pc端,移动端屏幕较小,无法正常展示除css布局。明显的解决方案是是viewport变宽一些。这时,就出现了将viewport分成两部分的情况,即:visual viewport和layout viewport 
“layout viewport可以比作一张不会变更大小或者形状的大图。现在想象有一个小一些的框架,通过它可以查看这个大图。这个框架的周围被不透明的材料所环绕,所以只能看到大图的一部分。通过这个框架看到的大图部分就是visual viewport。可以通过放大或缩小框架、甚至可以改变框架的方向来看大图,但是大图的大小和形状(layout viewport)是不会变化的“ 
visual viewport是页面当前显示在屏幕上的部分,用户可以通过滚动来改变他所看到的页面的部分,或者通过缩放来改变visual viewport的大小。 
css布局中,尤其是百分比宽度,是以layout viewport作为参考系计算的。所以html元素在初始情况下用的是layout viewport的宽度,并且css是在layout viewport基础上布局的。每个浏览器在移动设备上的默认layout viewport的宽度是不同的,一般为980px。

当对页面进行缩放时,visual viewport的尺寸会发生变化,layout viewport的尺寸仍然不变 
layout viewport的度量 
document.documentElement.clientWidth/Height包含了layout viewport的尺寸。layout viewport的宽度和高度等于在最大限度缩小的模式下屏幕上所能显示的任何内容的尺寸。移动设备的朝向会对高度产生影响,但对宽度不会产生影响。当在meta中设置width属性时,layout视图的宽度等于width设置的的宽度值。如果想让layout的宽度等于设备的宽度,可以设置如下:

<meta name='viewport' content="width=device-width">
  • 1
  • 2

visual viewport的度量 
对于visual viewport是通过window.innerWidth/Height(ie通过document.documentElement.offsetWidth/Height度量)来进行度量的。当用户缩小或放大的时候,度量的尺寸会发生变化。visual viewport的宽度等于设备的宽度/缩放比

滚动距离 
如需要知道visual viewport相对于当前layout viewport的位置,需要使用window.pageX/YOffset属性,ie将值存储在document.documentElement.scrollLeft/Top中 
document.documentElement.offsetWidth/Height返回以css像素为单位的html元素的整个尺寸

第三个视图

在这两个视图的基础上又出现了ideal viewport第三种视图。ideal viewport的宽度等于移动设备的屏幕宽度,只要在css中把某一元素的宽度设为ideal viewport宽度,那么这个元素的宽度就是设备屏幕的宽度了。ideal viewport的意义在于,无论在何种分辨率的屏幕下,那些针对ideal viewport而设计的网站,不需要用户手动缩放,也不需要出现横向滚动,都可以完美呈现

meta标签

meta标签中content属性可以设置的属性如下 
* width: 设置layout viewport的宽度 
* initial-scale:设置最初缩放比 
* minimum-scale:设置最小缩放比 
* maximum-scale:设置最大缩放比 
* user-scalable: 设置用户是否可缩放 
当设置width值为device-width或将initial-scale的值设为1时,相当于设置layout viewport的宽度等于ideal viewport的宽度.这里需要提醒一下,页面的缩放是相对于ideal viewport 的尺寸进行缩放的

<meta name='viewport' content="width=device-width">
<meta name='viewport' content="initial-scale=1">
  • 1
  • 2
  • 3

要把当前的viewport宽度设为ideal viewport的宽度,既可以设置width=device-width, 也可以设置initial-scale=1,但是这两者各有一个小缺陷,就是设置宽度属性时iphone/ipad会横竖屏不分、设置缩放比时windows phone上的IE会横竖屏不分,通通以竖屏的idealviewport宽度为准。所以最完美的写法是两者都写上

<meta name='viewport' content="width=device-width initial-scale=1">
  • 1
  • 2

可以通过setAttribute来动态改变meta viewport标签的值

<meta id="testViewport" name="viewport" content="width = 380">
<script>
var mvp = document.getElementById('testViewport');
mvp.setAttribute('content','width=480');
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

参考文献:两个viewport的故事(第一部分) 
两个viewport的故事(第二部分) 
移动前端开发之viewport的深入理解

猜你喜欢

转载自blog.csdn.net/qq_41813695/article/details/80551399