什么是移动端的完全适配

在移动端开发中,你需要面临的设备多种多样,他们的分辨率也很不相同。以iphone举例,iphone4的分辨率是960×640,而iphone6s plus的分辨率是1920x1080。当你的手中只有一份设计稿时,你怎样保证你的页面在不同的设备中都能完美显示呢?

这里,我们指的完全适配,是指同一份页面,在不同的屏幕中能够做到等比缩放,此处需要注意的是,由于不同设备不但分辨率数值不同,宽高比也不同,所以我们说的等比缩放通常是值相对于宽度或相对于高度的等比缩放。对于单屏页面(页面要求刚好占满一个屏幕)或滚屏页面(相当于多个单屏页面)来说,这里通常是根据高度等比缩放。而对于普通的、屏幕显示多少元素没有明显要求的,则是指根据宽度的等比缩放。本demo是根据高度的等比缩放。

项目需求

如图,我们拿到的设计稿是这样的:我们需要让这个页面不多不少,整整占满一个屏幕,这是一个典型的单屏页面,

什么是rem?

与em相似,rem同样表示一个字的字体大小,可以作为单位使用,在默认情况下1rem == 1em == 16px。既然rem表示字体大小,所以只要设置根元素html的font-size属性,让页面中所有子元素均继承这个属性,就可以控制整篇文档的字体大小。比如,设置html元素字体大小为20px,则在整个文档中,1rem和20px都是完全等等效的。

至于在实际应用中为什么选择rem而不是em进行计算,则是因为em会根据父元素的变动而变动。rem的参照则只有根元素,有兴趣的同学可以去查查rem与em的区别。

适配原理

假定为了完成一个单屏页面,我们需要对设计稿基于高度进行等比缩放。

经过测量,设计稿的高度为H,在设计稿中某个元素的高度为100px。

假定目标设备的高度为h,那么这个元素在目标设备中的高度为y。根据比例关系,可以很容易的得出y = 100 * H / h。如下图:

幸运的是,为了计算y而需要的变量,我们都可以得到,设计稿的数值宽高可以测量,设备的宽高可以通过JS获取,所以我们可以计算出y,再将让y = 1rem。这样我们就得到了一个等比的映射:100px等效1rem。

自然而然,50px等效0.5rem,我们在设计稿中测量的所有距离都可以等效为相应的rem,即可很轻松的进行等比缩放。

实现

首先,获取窗口和设计稿的宽高

//窗口的宽高
var wWidth = window.innerWidth,
    wHeight = window.innerHeight,
    //设计稿的宽高,此处需要填入
    myWidth = 552,
    myHeight = 738;

然后根据宽高进行等比缩放,确定设计稿中每100px在设备中对应的长度

// 根据高度等比缩放
var rem100 = 100 * wHeight / myHeight;
// 根据宽度等比缩放
var rem100 = 100 * wWigth / myWidth;
// 以上两种方法在实际使用中根据需求选择一种即可

最后将html元素的font-size属性设置为这个值,此处应该注意,我们既想尽可能早的设置好这个值,以免页面出现混乱,又必须保证html元素已经被完整加载,所以我们最好等到dom树加载完毕后在执行这一步,类似于jquery中常用的document.ready:

//dom树加载完毕后执行
document.addEventListener('DOMContentLoaded',function(){
    document.querySelector("html").style.fontSize = rem100 + 'px';
},false);

至此我们已经写好了一段通用的适配代码。那就用这段代码来实现本节的需求吧:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
        html,body{
            height: 100%;
            margin:0;
        }
        .container{
            background-image: url(5-1.png);
            background-size: cover;
            background-position: center;
            height: 100%;
            overflow: hidden;
        }
        .tt{
            margin:1.52rem auto 0;
            width: 3.24rem;
            height: 0.7rem;
            border:0.02rem solid #fff;
            font-size: 0.3rem;
            line-height: 0.7rem;
            color: #fff;
            white-space: nowrap;
            text-align: center;
            font-style: italic;
        }
        .cnt{
            width: 100%;
            margin-top: 2.26rem;
            color: #fff;
            font-size: 0.29rem;
            line-height: 0.53rem;
            white-space: nowrap;
            text-align: center;
            font-style: italic;
            background-color: rgba(0,0,0,0.5);
        }
    </style>
    <script>
        //窗口的宽高
        var wWidth = window.innerWidth,
            wHeight = window.innerHeight,
            //设计稿的宽高,此处需要填入
            myWidth = 406,
            myHeight = 608;
        // 根据高度等比缩放
        var rem100 = 100 * wHeight / myHeight;
        // 根据宽度等比缩放
        // var rem100 = 100 * wWigth / myWidth;
        //dom树加载完毕后执行
        document.addEventListener('DOMContentLoaded',function(){
            document.querySelector("html").style.fontSize = rem100 + 'px';
        },false);
    </script>
</head>
<body>
    <div class="container">
        <div class="tt">
            前端该玩的50个DEMO
        </div>
        <div class="cnt">
            移动端的适配
        </div>
    </div>
</body>
</html>