对手淘移动开发适配的实例思考
zhaoqize opened this issue · 0 comments
rem
从机型的实例来理解
机型: 小米5
- 物理像素(px): 1920 x 1080
- 独立像素(pt): 640 x 360
- dpr: 3
- 宽高比:16 : 9
机型: 红米note1s
- 物理像素(px): 1280 x 720
- 独立像素(pt): 640 x 360
- dpr: 2
- 宽高比: 16 : 9
问题:实现div
的宽度在不同机型上面的兼容
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>h5</title>
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0" name="viewport">
<style>
html,body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div style="width:200px; height: 30px; border: 1px solid red">
zqz测试数据
</div>
</body>
<script type="text/javascript">
alert('dpr:' + window.devicePixelRatio);
</script>
</html>
我们想要div
的宽度与屏幕的宽度相同,我们如果将div
的宽度写死肯定有问题,我们先写个width=720px
,效果如下:
很明显,两个手机全部都是右边超出了,你很定很好奇,物理像素不是720
么?至少红米手机应该显示正确把?
这里就牵扯到 物理像素(px)和 设备像素(dp/pt) 和 dpr 等概念。
物理像素(physical pixel)
物理像素又被称为设备像素,他是显示设备中一个最微小的物理部件。每个像素可以根据操作系统设置自己的颜色和亮度。正是这些设备像素的微小距离欺骗了我们肉眼看到的图像效果。
设备独立像素(density-independent pixel)
设备独立像素也称为密度无关像素,可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用的虚拟像素(比如说CSS像素),然后由相关系统转换为物理像素。
CSS像素
CSS像素是一个抽像的单位,主要使用在浏览器上,用来精确度量Web页面上的内容。一般情况之下,CSS像素称为与设备无关的像素(device-independent pixel),简称DIPs。
屏幕密度
屏幕密度是指一个设备表面上存在的像素数量,它通常以每英寸有多少像素来计算(PPI)。
设备像素比(device pixel ratio)
设备像素比简称为dpr,其定义了物理像素和设备独立像素的对应关系。它的值可以按下面的公式计算得到:
设备像素比 = 物理像素(px) / 设备独立像素(DP/PT)
更多手机信息见Device Metrics。
如果想要宽度正常的话,我们只需要将宽度改成width=360px
即可。因为这样的话
1个物理像素 = 1个设备独立像素
(其实这个里还有个问题,因为这两个手机的设备独立像素是一样的,所以无论写多少css像素
,在这两个机型上的表现是一致的)
当然这也是因为在有限的可见区域内,提高了像素密度
,显示就更清晰
。
- 小米5的设备的独立像素为
640pt x 360pt
,而其dpr为3
,所以我们知道其物理像素为1920px x 1080px
- 红米note的设备的独立像素为
640pt x 360pt
,但是其dpr为2
,所以我们知道其物理像素为1280px x 720px
在不同的屏幕上,CSS像素所呈现的物理尺寸是一致的,而不同的是CSS像素所对应的物理像素具数
是不一致的。在普通屏幕下 1 个CSS像素对应 1 个物理像素,而在dpr为2的屏幕下, 1 个CSS像素对应的却是 4 个物理像素。
我们希望的是我们写一个固定数值,而计算出不同的px。
rem
的出现,让我们这个想法得以实现。
针对上面红米和小米5的例子,我们可以这么设想:
1.在html中设置一个font-size是多少的情况下,div宽度设置多少rem,能够在 dpr=2 的手机中显示 360px 的宽度?
2.在html中设置一个font-size是多少的情况下,div宽度设置多少rem,能够在 dpr=3 的手机中显示 360px 的宽度?
手淘的适配方案的核心代码:
var dpr = window.devicePixelRatio;
var width = document.documentElement.getBoundingClientRect().width;
if (width / dpr > 540) {
width = 540 * dpr;
}
var rem = width / 10;
为什么是 540? 见540怎么得来的
这样的话,对于上面的2个自问,已经得出了答案:
1.在html中设置一个font-size是 (360/10)36px 的情况下,div宽度设置 10rem ,能够在 dpr=2 的手机中显示 360px 的宽度
2.在html中设置一个font-size是 (360/10)36px 的情况下,div宽度设置 10rem ,能够在 dpr=3 的手机中显示 360px 的宽度
- 在dpr=1的iphone3中呢?
- 在dpr=2的iphone6中呢?
获取参数:
iphone3
- dpr : 1
- dp : 320 x 480
- px : 320 x 480
iphone6
- dpr :2
- dp :375 x 667
- px : 750 x 1334
同样:
1.在html中设置一个font-size是 (320/10) 32px 的情况下,div宽度设置 10rem ,能够在 dpr=1 的手机中显示 320px 的宽度
2.在html中设置一个font-size是 (375/10) 37.5px 的情况下,div宽度设置 10rem ,能够在 dpr=2 的手机中显示 360px 的宽度
所以,目的达到,无论我们的设备宽度是多少,只要按照这个规律,我们只需要设置10rem
,必定会是屏幕的宽度。
参考: