10分钟从原理分析移动端H5适配方案,让你适配不再慌乱(一)

5,915 阅读6分钟

前言:前端的你,是否曾窃喜终于甩掉了IE6,却一个转身,猝不及防踏入移动端碎片大坑,今天过后,可以不用太过于纠结了,因为可以我帮你重塑对移动端的认识,从此以后,得心应手,提升效率不是梦。 知己知彼,百战不殆,我们前端开发也一样。知其然,知其所以然,不论从装逼或者实际开发的角度来说,都是百益而无一害的。我们来看一小段代码:

<html style="font-size:75px;" >
<head>
<meta name="viewport" content="initial-scale=0.5,maximun-scale=0.5,user-scalable=no" />
</head>
<body>
</body>
</html>

相信这个代码大家都已经很熟悉了,主要做了两个事,1、定义rem;2、定义viewport缩放比例。当然了,如果仅仅以为我又是炒这两盘人尽皆知的冷饭,那就太小看我咯。我们需要更加深入了解浏览器(当然包括webview啦),从而更加从容进行适配开发。 首先第一个问题,前端布局开发,到底是干嘛的呢?从本质上来讲,主要就是操作像素从而实现各种页面效果,那我们就从像素开始讲起咯。

一、首先,我们要知道几个基本概念。

1、css像素

我们使用css操作到的像素叫做css像素,也就是设备无关像素,顾名思义也就是与设备无关。

2、物理像素

既然有无关,那就肯定存在与设备有关的咯,也就是我们的物理像素了。我们操作css像素,然后由物理像素进行表达,在Retina屏出来以前,css像素的数量===物理像素,也就是说1css像素的图像就是通过1物理像素进行表达,在pc大屏上,这个效果是足够的,但是在手机浏览器中,是不够的,因此苹果率先推出Retina屏。

3、设备独立像素比

devicePixelRatio=物理像素/css像素,以下简称dpr,在Retina屏出来以前,dpr===1,Retina出现后,dpr>=1.5的屏幕如雨后春笋般出现。

4、屏幕分辨率

屏幕上显示的像素个数,在微软的pc时代很多人有个误解,屏幕分辨率跟屏幕大小成正比的,总觉得提升分辨率就要提升屏幕尺寸,其实不然,4k分辨率的屏都已应用到诺大一个手机屏了。

5、像素密度(ppi)

每英寸屏幕的像素数,这个属性跟屏幕分辨率是有直接关系的,一般来说,高像素密度的屏,屏幕分辨率也越大。

6、viewport

这是移动开发中及其重要的概念,早期移动端的viewport与pc的viewport是一个概念,导致小屏体验不佳,后来苹果引入可视视窗(visualviewport)和布局视窗(layoutviewport)。简单解释一下,这两个视窗是透视的效果,想象下layoutviewport是一张大的不能改变大小和角度的图片。我们透过visualviewport对layoutviewport进行观察(可以看看George Cummins在Stack Overflow上的解释)。观察距离远点(用户的缩小页面功能)就可以一次性看到这个大图。或者近点(用户的放大页面功能)可以看到一部分。你能改变这个透视框的方向,但这张大图片的大小和形状都不会改变。我们在<meta name="viewport" /> 设置的其实是layout-viewport,使得layoutviewport==visualviewport,达到idealviewport效果,使得viewport刚好完美覆盖屏幕,因此适配方案的时候,这一句最重要。

二、适配方案

我们在做布局方案的时候肯定是希望使用某种通用的布局方案,面对如此多的dpr,最好的方式就是根据dpr的不同比例进行适配,尽量避免使用媒体布局针对每一套设备进行适配,那真就成了搬砖码农。这里我会根据淘宝前端提供的flexible布局方案进行分析,回到我们开头的第一段代码,我们需要设置meta viewport和和rem,我们暂不考虑特殊情况,rem=window.innerWidth/10

1、第一种方案:根据dpr进行屏幕的缩放,达到dpr=1的效果

这种方案怎么理解呢,例如你的iphone6,Retina屏dpr=2,那么你的viewport meta设置应该如下:<meta name="viewport" content="initial-scale=0.5,user-scalable=no"/> 那么,这一句如何理解呢,因为dpr=2,说明一个css像素由2*2个物理像素进行表达,我们设置initial-scale=0.5也就是将我们的css像素大小缩小两倍,同一个屏幕上可用的css像素也就是变成了原来的两倍。比如设备尺寸375,dpr=2,这时候,我们可操作的像素值实际是375x2=750,我们进行换算的时候,rem=window.innerWidth/10=750/10=75,我们将这个75称为基准rem,这时候,我们的需要根据750的设计稿进行布局计算,也就是我们常说的二倍图。当不同的设备进行适配,只要根据实际计算的rem值与基数rem进行换算就达到了我们适配的目的。

2、第二种方案:无论dpr值为何,initial-scale=1

这种方案从本质上来讲,跟第一种方案是一致的,不过它保持了dpr带给我的原始特性,没有将css像素点进行缩放,这时候,同样以上述设备尺寸375,dpr=2进行举例,我们实际可操作的像素值依旧是375,这种情况下我们的基准rem就是window.innerWidth/10=375/10=37.5。

结论:以上两种虽然基准rem不同,但是方案在本质上是一致的

这如何理解呢?我们来举两个例子理解一下,1、因为都是相对于基准rem布局,假设我们需要全屏显示,width都是10rem。2、同样基于两倍图进行布局,比如我们有一张100*100大小的图片,我们需要显示100 *100大小,dpr=2的设备上显示,无论哪一种方案,必然模糊,首先来看第一种方案,像素点缩小一半导致模糊,第二种方案,每一个像素点都由4个像素进行渲染,只能取近似值,因此也会导致模糊,结果是都会模糊,但是两种方案都有其异同,因此我们想要在二倍屏显示100 *100的图片,图片也必须是二倍图,200 * 200。

结语

在了解了基本原理之后,相信你可以实现自己的一套布局方案了,当然了,如果嫌麻烦,不想重复造轮子,淘宝团队的flexible方案就够用了,原理是一致的嘛。

参考文档: