Skip to content

Latest commit

 

History

History
202 lines (142 loc) · 7.58 KB

移动端适配.md

File metadata and controls

202 lines (142 loc) · 7.58 KB

移动端适配

为理解各种适配方案的实现,首先先要了解一些基础概念

  • 物理像素:

    屏幕的物理像素又被称为设备像素,它是显示设备中一个最微小的物理部件,设备项目的物理像素出厂时就确定了且固定不变。

  • 设备独立像素

    设备独立像素也称为密度无关像素,可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用的虚拟像素(比如说CSS像素),然后由相关系统转换为物理像素

  • 设备像素比

    设备像素比简称为dpr,其定义了物理像素和设备独立像素的对应关系

    设备像素比 = 物理像素 / 设备独立像素
    以iphone6为例:
    iphone6的设备宽和高为375pt * 667pt,可以理解为设备的独立像素,而其设备像素比为2.固有设备像素为750pt * 1334pt
    

    通过:window.devicePixelRatio获得。

    设备像素比是区别是否是高清屏的标准,dpr大于1时就为高清屏,一般情况下dpr为整数,但是android有些奇葩机型不为整数

  • css像素

    在CSS、JS中使用的一个长度单位。单位px

    注:在pc端1物理像素等于1px,但是移动端1物理像素不一定等于1px,1物理像素与px的关系与以下因素有关

    • 屏幕布局视口大小
    • 屏幕的分辨率(物理像素) 对于一块屏幕,其物理像素是确定的。视觉视口尺寸是继承的布局视口的,而视觉视口里宽度即是css的px数。故在一块屏上物理像素与px的关系就是物理像素与布局视口的px数的关系。
    比如iphone6,期物理像素为750,如果没有设置布局视口时,viewport为980px
    此时:1物理像素长度等于980/750px = 1.3067px的长度
    由于像素都是点阵的,故1物理像素相当于1.3067px * 1.3067px方格。
    当在meta中设置了如下配置时
    <meta name="viewport" content="width=device-width">
    相当于把布局视口设置为设备的宽度(即上面讲到的设备独立像素) 对于iphone6就是375px。
    此时1物理像素长度等于375/750px = 0.5px的长度,故1物理像素相当于0.5px * 0.5px的方格
  • 布局视口 在html中一般在meta中的name为viewport字段就是控制的布局视口。布局视口一般都是浏览器厂商给的一个值。一般在768px ~ 1024px 之间,最常用的宽度就是 980。布局视口可以通过:

    document.documentElement.clientWidth(clientHeight) // 布局视口的尺寸。
  • 视觉视口 浏览器可视区域的大小,即用户看到的网页的区域

    window.innerWidth(innerHeight)  // 视觉视口尺寸
  • 理想视口 布局视口虽然解决了移动端查看pc端网页的问题,但是完全忽略了手机本身的尺寸。所以苹果引入了理想视口,它对设备来说是最理想的布局视口,用户不需要对页面进行缩放就能完美的显示整个页面。最简单的做法就是使布局视口宽度改成屏幕的宽度。可以通过window.screen.width获取。

    移动端到底怎么适配不同的屏幕呢?最简单的方法是设置如下视口:

    <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
     
方案一

固定高度,宽度自适应。

这种方案是目前使用较多的方案,也是相对较简单的实现方案:

该方法使用了理想视口:

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

垂直方向使用固定的值,水平方向使用弹性布局,元素采用定值、百分比、flex布局等。这种方案相对简单,还原度也非常低。

方案二

固定布局视口宽度,使用viewport进行缩放。固定布局视口,宽度设置固定的值,总宽度为640px,根据屏幕宽度动态生成viewport。(设计稿应该是640px的)。网易:

var win = window,
        width = 640,
        iw = win.innerWidth || width,
        ow = win.outerHeight || iw,
        sw = win.screen.width || iw,
        saw = win.screen.availWidth || iw,
        ih = win.innerHeight || width,
        oh = win.outerHeight || ih,
        ish = win.screen.height || ih,
        sah = win.screen.availHeight || ih,
        w = Math.min(iw, ow, sw, saw, ih, oh, ish, sah),
        ratio = w / width,
        dpr = win.devicePixelRatio;
        if (ratio = Math.min(ratio, dpr), 1 > ratio) {
            var ctt = ",initial-scale=" + ratio + ",maximum-scale=" + ratio,
                metas = document.getElementsByTagName("meta");ctt += "";
            for (var i = 0, meta; i < metas.length; i++) meta = metas[i], "viewport" == meta.name && (meta.content += ctt)
        }
方案三

根据不同屏幕动态写入font-size,以rem作为宽度单位,固定布局视口。

<meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    
    
75px 对应 0.75rem, 距离占设计稿的10%;

在ipone6上:
width = document.documentElement.clientWidth = 375px;
rem = 375px / 7.5 = 50px;
0.75rem = 37.5px;   (37.5/375=10%;占屏幕10%)
                     
在ipone5上:
width = document.documentElement.clientWidth = 320px;
rem = 320px / 7.5 = 42.667px;
0.75rem = 32px; (32/320=10%;占屏幕10%)    
方案四

以rem作为宽度单位,动态写入viewport和font-size进行缩放。根据设置的dpr设置font-size。如

document.documentElement.style.fontSize = 50 * dpr;
// dpr 为设置的设备像素比。(注意不是设备自身的设备像素比,而是认为设置的dpr)

这种情况下,dpr = 1时,1rem = 50px;

dpr = 2时, 1rem = 100px;

当设计以iphone6为标准,出750px的设计稿时,此时dpr=2,故1rem 等于100px,将图上的尺寸转换为rem非常方便,除以100就行。代码如下:

var scale             = 1.0;
var dpr             = 1;
var isAndroid         = window.navigator.appVersion.match(/android/gi);
var isIPhone          = window.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio  = window.devicePixelRatio;
// 此处只简单对ios做了伸缩处理,安卓没有做伸缩处理,统一dpr = 1
if ( isIPhone ) {
  scale /= devicePixelRatio;
  dpr *= devicePixelRatio;
}

var viewport        = document.getElementById('viewport');
var content         = 'initial-scale=' + scale + ', maximum-scale=' + scale + ',minimum-scale=' + scale + ', width=device-width, user-scalable=no';

viewport.setAttribute( 'content', content );
document.documentElement.style.fontSize = 50 * dpr + 'px';
document.documentElement.setAttribute('data-dpr', dpr);
方案五

根据不同屏幕动态写入font-size和viewport,以rem作为宽度单位

将屏幕分为固定的块数10:

var width = document.documentElement.clientWidth;   // 屏幕的布局视口宽度
var rem = width / 10;                               // 将布局视口分为10份

这样在任何屏幕下,总长度都为10rem。1rem对应的值也不固定,与屏幕的布局视口宽度有关。

对于动态生成viewport,他们原理差不多,根据dpr来设置缩放。看看淘宝的:

var devicePixelRatio = window.devicePixelRatio;
var isIPhone = window.navigator.appVersion.match(/iphone/gi);
var dpr,scale;
if (isIPhone) {
  if (devicePixelRatio >=3) {
    dpr = 3;
  } else if (devicePixelRatio >=2) {
    dpr = 2;
  } else {
    dpr = 1;
  }
} else {
  dpr = 1;
}
scale = 1 / dpr;