目录
0. 为什么要写这篇文章?1. 设备像素比的问题在哪里?1.1. 不同的论述导致不同的理解1.2. 设备独立像素与CSS像素1.3. 小结2. 设备像素比 = 设备物理像素/CSS像素,真的正确吗?2.1. PC端验证2.2. 手机端验证2.3. 出了什么问题?2.4. 重新认识设备像素比3. 总结0. 为什么要写这篇文章?
最近查阅了一些移动端适配的文章和资料,对大多数的概念和论述没发现有疑惑的地方,唯独对设备像素比(device pixel ratio,dpr)有些不解,而设备像素比对理解移动端概念以及适配都起到重要作用,所以做了更多的资料查阅和理解,这期间花了一些时间,也希望有不同意见的同学可以交流一下
ps:这篇文章不是移动端适配入门文章,不对大多数基础概念进行解释,例如像素,viewport,meta标签和主流适配方案等,如果还没了解基础概念,建议读一下相关文章再来看(也可以先阅读我下面列出的参考文章,自己先理解一下 ^ _ ^)
1. 设备像素比的问题在哪里?
1.1. 不同的论述导致不同的理解
实际上,我在查阅文章的时候,发现不同文章对这个概念的论述存在差异性,而这个差异性容易导致理解的差异,大致可以归类为两种结论:
结论1:设备像素比 = 设备物理像素/设备独立像素
参考文章1:关于移动端适配,你必须要知道的
参考文章2:面试官:你了解过移动端适配吗?
参考文章3:移动前端开发之viewport的深入理解
参考文章4:使用Flexible实现手淘H5页面的终端适配
参考文章5:设备像素比devicePixelRatio简单介绍
参考文章6:what exactly is device pixel ratio?
结论2:设备像素比 = 设备物理像素/CSS像素
参考文章7: 年移动端适配方案指南
参考文章8:作为前端,你应该了解的分辨率/逻辑像素/物理像素/retina屏知识
参考文章9:完全理解px,dpr,dpi,dip
参考文章10:前端涉及的各种像素概念以及 viewport 汇总
设备像素比在浏览器下可以用window.devicePixelRatio
接口获取,MDN是这样定义的:Window 接口的devicePixelRatio返回当前显示设备的物理像素分辨率与CSS像素分辨率之比。 此值也可以解释为像素大小的比率:一个CSS像素的大小与一个物理像素的大小。 简单来说,它告诉浏览器应使用多少屏幕实际像素来绘制单个CSS像素。
根据此定义,CSS像素是可变的,设备像素比应该也是可变的,所以结论2比较准确,但是还有一个可能,有没有可能设备独立像素就是相当于CSS像素呢?若是,则结论1也可以成立。下面继续讨论
1.2. 设备独立像素与CSS像素
综合分析1.1.节的参考文章,首先明确一个基本没有争议的结论:CSS大小是可变的,跟缩放有关。但关于设备独立像素与CSS像素的关系,有如下两种结论:
结论3:设备独立像素为固定值,与css像素成缩放比例的关系,见: 参考文章1,参考文章4, 参考文章5,参考文章6,参考文章7, 参考文章9
结论4:设备独立像素就是css像素,见:参考文章3, 参考文章8,参考文章10
我们回到设备独立像素出现的背景,设备独立像素是随着Retina屏的诞生而出现的,下面是apple开发网站的尺寸标注:
px是设备物理像素,pt是设备独立像素,@x等于 设备物理像素/设备独立像素,在chrome开发工具,adobe,dpi.lv,mydevice.io等网站也可以看到类似的标注
由此可见,设备独立像素是一个与设备物理像素相对应的抽象尺寸标准,应该是不可变的,设备物理像素/设备独立像素的比值衡量的是设备在初始状态下(无缩放,缩放比例100%)用程序绘制一个抽象像素需要使用多少真实的像素,而无缩放的状态下,CSS像素是可以等价于设备独立像素的,在有缩放的状态下,缩放比例就是CSS像素与设备独立像素的比值,所以我们可以得出结论3(设备独立像素为固定值,与css像素成缩放比例的关系)是正确的
PPK在iPhone 4到来之前写了一篇文章,有一段话是这么描述的:
When the zooming factor is exactly 100%, one CSS pixel equals one device pixel (though the upcoming intermediate layer will take the place of device pixels here.)
当缩放因子等于100%的时候,一个CSS像素等于一个设备像素(尽管在即将到来的中间层会取代这里的设备像素)
注意括号里面的话,即将到来的中间层也就是后面出现的设备独立像素的概念,也就是设备独立像素对标的是原来的设备物理像素,例如原来说在300%缩放的情况下1个CSS像素等于3个设备物理像素,以后就要说成1个CSS像素等于3个设备独立像素了,PPK这段话也间接印证了结论3
1.3. 小结
我们再回顾一下1.1.和1.2.得出的结论:
结论1:设备像素比 = 设备物理像素/设备独立像素
结论2:设备像素比 = 设备物理像素/CSS像素
结论3:设备独立像素为固定值,与css像素成缩放比例的关系
结论4:设备独立像素就是css像素
综合结论2和结论3,可以得出
结论5:设备像素比 = 设备物理像素/CSS像素;而设备独立像素为固定值,在无缩放的时候与CSS像素等价
而且你会发现,结论1和结论4只是结论5的在无缩放条件下的特例
另外,设备物理像素/设备独立像素,如果非要用一个词来指代,我觉得使用apple官网的scale factor(缩放因子)来描述挺合适的,即 scale factor=设备物理像素/设备独立像素,该值不可变
High-resolution displays have a higher pixel density, offering a scale factor of 2.0 or 3.0 (referred to as @2x and @3x).
2. 设备像素比 = 设备物理像素/CSS像素,真的正确吗?
好了,有了1.3.小结的结论,我们满怀欣喜地带着这个结论继续往前走
2.1. PC端验证
无缩放状态下:
设备像素比2,然后是各个宽度:设备独立像素1500,布局视口1500,测试元素宽度200,可反推出设备物理像素3000
基于无缩放状态下的数值,测试200%和50%缩放的数值,以下是我们的预期数值
实际数据,见下图
数值符合预期,设备像素比 = 设备物理像素/CSS像素通过验证
2.2. 手机端验证
使用iPhone6作为测试机型,iPhone6的设备独立像素为375 x 667,设备物理像素为750 x 1334,缩放因子为2
无缩放状态下:
设备像素比2,然后是各个宽度:设备独立像素375,布局视口375,测试元素宽度200,可反推出设备物理像素750
基于无缩放状态下的数值,测试200%和50%缩放的数值,缩放数值通过<meta name="viewport" content="width=device-width, initial-scale=1">
标签的initial-scale
属性设置,以下是我们的预期数值
实际数据,见下图
真机效果
数值符合…等等,数据好像不符合预期?!
在手机端,设备像素比没有随着缩放比而变化?
2.3. 出了什么问题?
我们来看看出了什么问题,根据公式设备像素比 = 设备物理像素/CSS像素,设备物理像素不变,在3种缩放比例下,我们可以看到测试像素的CSS宽度均为200不变,而测试像素实际大小已发生了变化,说明CSS像素随着缩放覆盖了更多/更少的设备独立像素/设备物理像素,根据上面的公式,设备像素比是应该按预期发生变化的,然鹅,现在我们只在PC端看到了我们预期,在移动端设备像素比似乎不随缩放发生变化
再回过头来看看1.1.节关于MDN对设备像素比的定义:Window 接口的devicePixelRatio返回当前显示设备的物理像素分辨率与CSS像素分辨率之比。 此值也可以解释为像素大小的比率:一个CSS像素的大小与一个物理像素的大小。 简单来说,它告诉浏览器应使用多少屏幕实际像素来绘制单个CSS像素。
以上定义跟我们目前的认知一致,仍然没办法解释为什么移动端设备像素比不随缩放发生变化
2.4. 重新认识设备像素比
对于2.3.节出现的问题,困扰了我一段时间,直到我找到了一份window.devicePixelRatio的规范,如下:
The devicePixelRatio attribute must return the result of the followingdetermine the device pixel ratioalgorithm:
If there is no output device, return 1 and abort these steps.Let CSS pixel size be the size of a CSS pixel at the current page zoom scale factor and at a pinch zoom scale factor of 1.0.Let device pixel size be the vertical size of a device pixel of the output device.Return the result of dividing CSS pixel size by device pixel size.
从第4点来看,window.devicePixelRatio返回的结果是CSS像素大小与设备物理像素大小之比,这和我们的公式设备像素比 = 设备物理像素/CSS像素是一致的(注意,我们公式的像素单位是个数,规范第4点的单位是大小,所以除数和被除数会相反,但表达的意思是一致的)
既然结论没有问题,那是不是可能我们忽略了结论成立的某些前提条件,我们留意到规范第2点:
Let CSS pixel size be the size of a CSS pixel at the currentpage zoomscale factor and at apinch zoomscale factor of 1.0.使CSS像素大小为当前page zoom的缩放比例且pinch zoom缩放比例等于1之下的CSS像素大小
在这里,我们获悉了之前对设备像素比的定义中都没有提到的前提条件:
条件1:计算当前page zoom的缩放比例
条件2:使pinch zoom缩放比例等于1,换句话说,就是不计算page zoom的缩放比例
这两个条件其实给我们澄清了两种缩放:page zoom也就是页面缩放(例如在PC端使用Ctrl+鼠标滚轮/+/-),pinch zoom是手势缩放或者双指缩放。为什么计算设备像素比的时候要计算page zoom而不计算pinch zoom呢?有何区别呢?zoom的规范是这么说的:
There are two kinds of zoom,page zoom which affects the size of the initial viewport, andpinch zoomwhich acts like a magnifying glass anddoes not affect the initial viewport or actual viewport.
存在两种缩放:会影响初始视口的页面缩放,和类似放大镜一样不会影响初始或实际视口的手势缩放
可对页面缩放和手势缩放可以得出如下结论:
结论6:页面缩放会影响页面的布局视口,会引起页面的重新布局,所以设备像素比需计算页面缩放的比例
结论7:手势缩放不会影响布局视口,不会引起页面重新布局,只会影响视觉视口,类似放大镜的功能,所以设备像素比不需计算手势缩放的比例,在计算设备像素比的时候CSS像素大小按照手势缩放比为1的大小计算
结论6已经在2.1.节验证了,为了验证结论7,我们利用笔记本的触摸板,来模拟实际设备的手势缩放(pinch zoom)功能(带触摸屏功能的电脑也可以直接在屏幕上操作)
PC端
移动端
可以看到,无论在PC端还是手机端,手势缩放不会影响布局视口,只会影响视觉视口,在只改变手势缩放的条件下,设备像素比保持不变,结论6验证通过
至此,对于2.2.和2.3.出现的问题:在移动端设备像素比不随缩放发生变化,也随着结论5和结论6的确定而解决了,因为移动端进行的是手势缩放(pinch zoom)而非页面缩放(page zoom),故设备像素比保持不变
ps:有意思的是,现在移动端浏览器似乎没有给我们提供类似PC端页面缩放的功能而只有手势缩放功能,也就意味着移动端的设备像素比在目前是可以“保持不变的”,也就意味着移动端在某种程度上,结论1(设备像素比 = 设备物理像素/设备独立像素)和结论4(设备独立像素就是css像素)确实是可以成立的,但如果没弄清楚为什么,就很容易造成概念和结论的混淆。而且谁也说不定哪一天移动端会不会有类似页面缩放(page zoom)的功能,万一呢?^ _ ^
3. 总结
根据结论5,6,7,有:
结论5:设备像素比 = 设备物理像素/CSS像素,而设备独立像素为固定值,在无缩放的时候与CSS像素等价
结论6:页面缩放会影响页面的布局视口,会引起页面的重新布局,所以设备像素比需计算页面缩放的比例
结论7:手势缩放不会影响布局视口,不会引起页面重新布局,只会影响视觉视口,类似放大镜的功能,所以设备像素比不需计算手势缩放的比例,在计算设备像素比的时候CSS像素大小按照手势缩放比为1的大小计算
把上面的3个结论总结到一起,可以得出对设备像素比的最终结论:
设备像素比 = 设备物理像素/CSS像素,CSS像素的实际大小只受页面缩放(page zoom)的影响而不受手势缩放(pinch zoom)的影响;设备独立像素为固定值,在无缩放的时候与CSS像素等价
以上就是我查阅相关资料并逐步理清疑惑的过程,欢迎多多交流