屏幕是由一个一个显示单元组成的.
1 每个显示单元都是物理世界真实存在的;
2 把一个显示单元的大小称为一个'物理像素';
3 一般咱们所说的 '分辨率', 就是指一块屏幕显示单元的个数, 好比 750 叉 1334, 表示这块屏幕由 750叉1334 个显示单元组成javascript
一般状况下, 1 个显示单元对应 计算机系统中的 1px.
也就是说, 若是你设置了一个元素的 height:100px; 在屏幕中会有 100个显示单元来渲染它.
后来出现了一种状况
在相同大小的屏幕下,
屏幕分辨率不同, 一个分辨率是 A, 而另一个分辨率是 2A --- 由于咱们能够把显示单元作的更小了html
这种状况的出现, 有以下的影响java
若是咱们维持着: 计算机系统中的 1px, 对应物理上的 1个显示单元.
那么一样一个页面, 在 A 显示正常, 在 2A 的情景下面, 就只会显示一半.浏览器
这种状况确定是不能够的.因此咱们须要针对这种状况作处理: 浏览器提供了一个 devicePixelRatio(设备像素比) 的属性, 用来标记:ide
标准显示单元的大小/当前设备的显示单元的大小
而且明确两条规则:布局
1px 始终对应 1个显示单元idea
标准的 1个显示单元大小为 x, 其余的显示单元, 多是 1/2x, 1/3xcode
咱们能够经过判断这个值, 来调整咱们使用的 px 的大小,
好比:htm
devicePixelRatio = 1 的设备中, 元素a 的宽度为 100px; devicePixelRatio = 2 的设备中, 元素a 的宽度为 200px;
ok, 那么咱们来搞.
根据不一样的 devicePixelRatio 来调整元素的样式.ip
var box = document.querySelector('.box'); var height = parseInt(getComputedStyle(box).height); var width = parseInt(getComputedStyle(box).width); box.style.height = height * parseInt(window.devicePixelRatio) + 'px'; box.style.width = width * parseInt(window.devicePixelRatio) + 'px';
这仅仅是一个元素的两个属性, 1000个元素, 每一个元素 5 个属性, 就可让你哭掉了.
因此这种处理方式确定是不能够的.
而后咱们发现了 rem 单位.
它的简单解释:
当你给某个元素A 设置了 height:2rem 的时候 它会找到根节点(html) 的 font-size 值, 好比是 16px 而后拿 16 * 2 = 32px 做为元素A 的最终 height.
这个就能够利用了
让元素使用 rem 做单位
而后控制根元素的 font-size 值, 在不一样的 devicePixelRatio 下面的时候, 呈现不一样的值
好比: devicePixelRatio = 1, font-size(root) = 100px; devicePixelRatio = 2, font-size(root) = 200px;
元素在这个时候, 就会自动响应大小的变化.
好, 开始搞:
var fontSize = 100 * parseInt(window.devicePixelRatio) + 'px'; document.documentElement.style.fontSize = fontSize;
嗯, 结果仍是不错的, 在不一样的分辨率下面, 咱们也能实现页面相同了.
而后你会老是以为, pc 上面的 100px, 和你 devicePixelRatio=2 的时候的 200px
的大小不一致的, 按道理来讲应该是一致的.
的确不一致.
先明确一个概念
浏览器可视区域(visual viewport)
咱们以前说了 '计算机系统中的 1px 始终对应 1个物理显示单元'
那么对应 750*1334 分辨率的屏幕, 咱们一样能够这么描述它:
屏幕的大小为 750px*1334px.
前面已经说过了, 相同物理尺寸的屏幕, 分辨率可能不一样, 由于显示单元的个数不一样.
因此这里的 750px, 可能仅仅是标准下面的 375px;
另一个概念:ideal viewport
它表示的是说:
当前设备, 使用标准显示单元为单位的时候的大小.
好比说 750*x 的分辨率, devicePixelRatio = 2,
那么它在标准显示单元下面, 宽度就是 375px * x/2
最后咱们提一下 layout viewport, 这是为何大小不一致的缘由:
历史:
从 iPhone 发布前夕提及, 开发人员发现, 本来为 pc 开发的网页 在 iPhone 上面显示不全, 这部分能够经过滚动条来解决. 可是使用 百分比布局的页面就坑爹了, 本来在 pc 端浏览器上拥有 的 20% 在 iPhone 上面就一点点了, 布局彻底乱了, 坑啊. 为了解决这个问题, 开发人员提出了一个的新的概念: 'layout viewport'
layout viewport的默认大小为 980px, 而且默认缩放到和 visual viewport 区域通常大小.
在这种状况下, 咱们能够计算出layout viewport下,
一个 100px 宽度的元素, 对应的 visual viewport 下面的宽度 x
layout viewport / visual viewport = ele-width(layout viewport) / x
也就是
x = ele-width(layout viewport) * (layout viewport / visual viewport);
ideal viewport 下面的宽度, 只要再除以 devicePixelRatio 便可.
很明显的看出来:
width(layout viewport) = width(visual viewport) 的时候, 两个 viewport 中的元素宽度值
是相等的.
width(visual viewport) / devicePixelRatio = ideal viewport 中的元素的大小.
而咱们的最终追求, 就是
当你写下 100px 的时候, 在任何 devicePixelRatio 下面的大小都是一致的.
要作到这一点, 就要作到它们的 ideal viewport 下面的大小始终一致的.
而一个元素在 ideal viewport 下的大小的计算公式为:
( ele-width(layout viewport) * (layout viewport / visual viewport) ) / devicePixelRatio;
由于不一样的设备的 visual viewport 的值是不一样的, 咱们能够控制让 layout viewport 的大小始终
等于 visual viewport, 这样比例始终为 1
devicePixelRatio 在不一样的设备中有不一样
假设 ele-width(ideal viewport) = x; devicePixelRatio = n; 那么 ele-width(layout viewport) = nx;
因此咱们只要保证, ele-width 的宽度, 始终为 nx 便可, 由于一般状况下咱们是知道 x 的.
how?
控制 layout viewport 的大小始终等于 visual viewport
经过 meta name="viewport" 的 content 的 initial-scale 来控制.
initial-scale = 1 , layout viewport 的宽度为 375 (同ideal viewport) initial-scale = 2 , layout viewport 的宽度为 188 initial-scale = 0.5, layout viewport 的宽度为 750;
因此获得的结论:
当 initial-scale 的值为 1/devicePixelRatio 的时候, width(layout viewport) = width(visual viewport)
2 经过 rem, 以及根据不一样的 devicePixelRatio 设置 根节点的 font-size 值, 来控制 nx 的值的大小.
而后须要给出一份基准值:
在 750(visual viewport), devicePixelRatio = 2 的时候, root(font-size) = 200px;
若是都作到这里了, 那么至少能够达到:
在不一样的 devicePixelRatio 下面元素的大小都是一致的.
可是依旧存在一个问题, 当前页面是基于 750 (visual viewport) 定义的, 也就是说
当你的设备实际上只有 640(visual viewport) 的时候,
你的整个页面仍是 750px, 就会出现滚动条.
因此咱们想要等比缩放一下.
如何操做?
直接等比缩放一下 root(font-size) 的值:
750/200 = 640/x x = 640 / (750 / 200)