More than code
Welcome to the website

移动端高清、多屏适配方案

一、基本概念

1. 设备像素(device pixel, dp):


设备像素又称物理像素(physical pixel),一个物理像素是显示器(手机屏幕)上最小的物理显示单元,意指显示器上一个个的点。从屏幕在工厂生产出的那天起,它上面设备像素点就固定不变了,单位 pt。在操作系统的调度下,每一个设备像素都有自己的颜色值和亮度值。

2. CSS像素:


CSS像素也被称为逻辑像素,是Web编程的概念,独立于设备的用于逻辑上衡量像素的单位,也就是说我们在做网页时用到的CSS像素单位,是抽象的,而不是实际存在的。

3. 设备独立像素(density-independent pixel,dip):


设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css像素,只是在android机中CSS像素就不叫“CSS像素”了而是叫”设备独立像素”),然后由相关系统转换为物理像素。所以说,物理像素和设备独立像素之间存在着一定的对应关系,这就是接下来要说的设备像素比

4. 设备像素比(device pixel ratio,dpr):


设备像素比 = 设备像素 / 设备独立像素     // 在某一方向上,x方向或者y方向,单位:dpi

在javascript中,可以通过window.devicePixelRatio获取到当前设备的dpr。

在css中,可以通过-webkit-device-pixel-ratio-webkit-min-device-pixel-ratio-webkit-max-device-pixel-ratio进行媒体查询,对不同dpr的设备,做一些样式适配(这里只针对webkit内核的浏览器和webview)。

5. 物理像素和设备对像素的关系:


在一定的条件下两者它们两者是可以相等的,比如:在PC端浏览器默认情况下(100%,即页面没被缩放),一个物理像素 = 一个设备独立像素。而在移动端可就不一样的,为了让画质更精细,这两个值很多时候是不相等的。这里就该提到一个叫ppi的东西。

PPI 全称是(pixel per inch)翻译下就是每英寸内有多少个像素点,这个像素点指的是设备像素点(物理像素),说得接地气点PPI就是像素密度(pixel density)。PPI的值越高,画质越好,也就是越细腻,看起来更有逼格。计算公式如下:

综合上面几个基本概念,举例如下:

iphone6为例:

  1. 分辨率750pt×1334pt:指屏幕上垂直有1334个物理像素,水平有750个物理像素。
  2. 设备宽高375×667,可以理解为设备独立像素(或css像素)。
  3. dpr为2,根据上面的计算公式,其物理像素就是(375×667)×2,为750×1334
  4. 屏幕尺寸4.7英寸,注意英寸是长度单位,不是面积单位。4英寸指的是屏幕对角线的长度。
  5. 屏幕像素密度:根据上面的公式可以计算出ppi为326dpi

上图中可以看出,对于这样的css样式:

width: 2px;
height: 2px;

在不同的屏幕上(普通屏幕 vs retina屏幕),css像素所呈现的大小(物理尺寸)是一致的,不同的是1个css像素所对应的物理像素个数是不一致的。

在普通屏幕下,1个css像素 对应 1个物理像素(1:1)。 在retina 屏幕下,1个css像素对应 4个物理像素(1:4)。

6. 视口


桌面浏览器中,浏览器的视口就是约束你的css布局视口(又称初始包含块)。它是所有CSS百分比宽度推算的根源,它的作用是给CSS布局限制了一个最大宽度,视口的宽度和浏览器窗口宽度一致。

但是在移动端,情况比较复杂。

6.1 布局视口

一个没有为移动端做优化的网页,会尽可能缩小网页让用户看到所有东西。比如说,以前的博客园:

浏览器厂商为了让用户在小屏幕下网页也能够显示地很好,所以把视口宽度设置地很大,一般在 768px ~ 1024px 之间,最常见的宽度是 980px。

所以,在手机上,视口与移动端浏览器屏幕宽度不再相关联,是完全独立的,这个浏览器厂商定的视口被称为布局视口

布局视口我们是看不见的,只知道网页的最大宽度是 980px ,并且被缩放在了屏幕内。可以这样设置布局视口的宽度:

<meta name="viewport" content="width=640">

6.2 媒体查询与布局视口

700px指的是布局视口的宽度

@media (min-width: 700px){
 ...
}

document.documentElement.clientWidth/Height返回布局视口的尺寸

6.3 视觉视口

视觉视口是用户正在看到的网页的区域,大小是屏幕中CSS像素的数量。

window.innerWidth/Height返回视觉视口的尺寸

6.4 理想视口

布局视口明显对用户是不友好的,完全忽略了手机本身的尺寸。所以苹果引入了理想视口的概念,它是对设备来说最理想的布局视口尺寸。理想视口中的网页用户最理想的宽度,用户进入页面的时候不需要缩放。

现在讨论所谓的『最理想的宽度』到底是多少?其实,如果我们把布局视口的宽度改成屏幕的宽度不就不用缩放了么。可以这样设置告诉浏览器使用它的理想视口:

<meta name="viewport" content="width=device-width">

定义理想视口是浏览器的事情,并不能简单地认为是开发者定义的,开发者只能使用。

screen.width/height返回理想视口的尺寸,有严重的兼容性问题—可能返回两种值:

理想视口的尺寸(下载浏览器)
屏幕的设备像素尺寸(内置浏览器)

Understanding viewportk可以测试设备的screen.width值,同一设备的不同浏览器返回的值可能是不一样的。这一情况主要发生在默认浏览器和下载浏览器(如UC、Chrome)之间。

默认浏览器是安卓系统内置的浏览器,它使用的是Webkit而不是Blink。只有在更新安卓系统的时候才能更新它。直到安卓4.3,Google不再更新。下载浏览器都返回的是理想视口尺寸。

7. 缩放


7.1 缩放与设备像素、CSS像素的关系

缩放是在放大或缩小CSS像素,比如一个宽度为 200px 的元素无论放大多少倍,还是200个CSS像素。但是因为这些像素被放大了,所以CSS像素也就跨越了更多的设备像素。缩小则相反。

7.2 缩放与视口

缩放会影响视觉视口的尺寸

页面被用户放大,视觉视口内CSS像素数量减少;被用户缩小,视觉视口内CSS像素数量增多就行了。这个道理应该是不难想的。

用户缩放不会影响布局视口

注意,这是『用户缩放』,后面会说开发者设置缩放的情况

7.3 缩放比例

我们在开发者工具中可以在这里查看缩放比例:

这里的0.3是相对于理想视口的。

在下载浏览器中,可以这么算(理想视口与视觉视口的比):

zoom level = screen.width / window.innerWidth

7.4 禁止缩放和设置缩放

<meta name="viewport" content="user-scalable=no">//禁止缩放
<meta name="viewport" content="initial-scale=2">//设置缩放

使用initial-scale有一个副作用:同时也会将布局视口的尺寸设置为缩放后的尺寸。所以initial-scale=1与width=device-width的效果是一样的。

8. 完美视口


使用initial-scale有一个副作用:同时也会将布局视口的尺寸设置为缩放后的尺寸。所以initial-scale=1与width=device-width的效果是一样的。

<meta name="viewport" content="width=device-width,initial-scale=1">

9. 再谈设备像素比


在谈到像素的时候,讲到除了缩放,屏幕是否为高密度也会影响设备像素和CSS像素的关系。

缩放程度为100%(这个条件很重要,因为缩放也会影响他们)时,他们的比例叫做设备像素比(device pixel ratio):

dpr = 设备像素 / CSS像素

可以通过JS得到: window.devicePixelRatio

设备像素比也和视口有关:

dpr = 屏幕横向设备像素 / 理想视口的宽

二、适配方案

1.  固定高度,宽度自适应

这也是目前使用最多的方法,垂直方向用定值,水平方向用百分比、定值、flex都行。腾讯京东百度天猫亚马逊的首页都是使用的这种方法。

随着屏幕宽度变化,页面也会跟着变化,效果就和PC页面的流体布局差不多,在哪个宽度需要调整的时候使用_响应式布局_调调就行(比如网易新闻),这样就实现了『适配』。

原理:

这种方法使用了完美视口:

<meta name="viewport" content="width=device-width,initial-scale=1">

这样设置之后,我们就可以不用管手机屏幕的尺寸进行开发了。

2. 固定宽度,viewport缩放

设计图、页面宽度、viewport width使用一个宽度,浏览器帮我们完成缩放。单位使用px即可。

目前已知荔枝FM网易新闻在使用这种方法。有兴趣的同学可以看看是怎么做的。

原理

这种方法需要根据屏幕宽度来动态生成viewport,生成的 viewport 基本是这样:

<meta name="viewport" content="width=640,initial-scale=0.5,maximum-scale=0.5,minimum-scale=0.5,user-scalable=no">

640 是我们根据设计图定下的,0.5 是根据屏幕宽度动态生成的。

生成的viewport告诉浏览器网页的布局视口使用 640px,然后把页面缩放成50%,这是绝对的等比例缩放。图片、文字等等所有元素都被缩放在手机屏幕中。

这个gif图说明了一切:

3. 固定宽度,viewport缩放

这也是淘宝使用的方案,根据屏幕宽度设定 rem 值,需要适配的元素都使用 rem 为单位,不需要适配的元素还是使用 px 为单位。

具体使用方法见使用Flexible实现手淘H5页面的终端适配

我这里给出less的px2rem。因为less不支持函数,所以需要安装插件 less-plugin-functions ,然后就简单了:

.function{
    .px2rem(@px,@base:72px){
        return: @px / @base * 1rem;
    }    
}

这样使用:

div{
    width: px2rem(100px);
}

使用这个方法的库:

原理

实际上做了这几件事情:

  1. 动态生成 viewport
  2. 屏幕宽度设置 rem的大小,即给<html>设置font-size
  3. 根据设备像素比(window.devicePixelRatio)给<html>设置data-dpr

这么设置的好处是可以让不同设备的rempx都显示一样的长度。

设置rem

设置rem的意义在于得到一个与屏幕宽度相关的单位,本来vw是最合适的,但是因为兼容性的问题,只能使用rem来做。这样,让不同设备的rem显示一样的长度

vw是CSS3引入的单位,1vw = 1%窗口宽度

上面的布局我们可以这样:

html{
    font-size: 屏幕宽度 / 10; 
}
.btn{
    width:8.75rem;
    height:1.25rem;
}

这样,无论屏幕宽度是多少,.btn都是相对于屏幕的这么宽,做到了适配。

设置 viewport 缩放 和 data-dpr

这两个设置其实是干的一件事,就是适配高密度屏幕手机的px单位。

.a{
  font-size:12px;
}
[data-dpr="2"] .a{
  font-size: 24px;
}
[data-dpr="3"] .a{
  font-size: 36px;
}

而缩放是动态的,这样,不同设备下的px显示一样的长度

之前说过CSS像素和物理像素与缩放、dpr都有关系,这里说明:

在普通手机上,.a字体设置为12px;

在dpr是2的手机上,[data-dpr="2"] .a字体为24px,又因为页面缩放50%,字体为还是12px

4. 总结

个人认为第三种方案是相对比较好的方案。参考以上方案,来根据我们的需求实现自己的方案。

5. 具体实现方式

5.1 动态设置viewport的scale

var scale = 1 / devicePixelRatio; 
document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

5.2 动态设置html的font-size、data-dpr

function refreshRem() {
   var rem = docEl.clientWidth / 10;
   docEl.style.fontSize = rem + 'px';
}

5.3 布局的时候,各元素的css尺寸=设计稿标注尺寸/(设计稿横向分辨率/10)

比如:设计稿是750的,那html的font-size就是75px,如果某个元素的宽度是150px,换算成rem就是150 / 75 = 2rem。

5.4 font-size需要额外的媒介查询,并且font-size不使用rem

div { 
 width: 1rem; 
 height: 0.4rem;
 font-size: 12px; // 默认写上dpr为1的fontSize
}
[data-dpr="2"] div {
 font-size: 24px;
}
[data-dpr="3"] div {
 font-size: 36px;
}

三、演示Demo和源码

适配方案会不断优化更新,代码请移步github https://github.com/li-shuaishuai/screen_flex

效果图(设计图为横屏):

赞(0) 打赏
未经允许不得转载:李帅帅空间 » 移动端高清、多屏适配方案

相关推荐

  • 暂无文章

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏