移动端前端开发设计稿及工作流的探索和思考

3940次浏览

今天我们再来说说移动端的前端开发。关于移动端的一些注意事项,我前面写过几篇文章。例如手机网站几点注意问题 等等。这些都是在我们手机开发中遇到的问题。但是当我们拿到移动端的设计稿的时候,如何让我们的设计稿更好的适应各种手机屏幕?又因为设计稿尺寸一般是我们正常手机屏幕的2-3倍,假如我们拿到移动端的设计稿宽度尺寸是640,如何才能把这个640的尺寸中的各个元素精确的拿到呢?

我们的探索

之前传统做法:

我前面也有几篇文章,说到过rem单位,例如:CSS的单位rem的看法 等。起初,我们做移动端开发的时候,拿到设计师们的设计图的时候,发现尺寸很大,和我们实际布局网页宽度,320、375有出入。那么如何进行移动端的布局呢?我们运用了最笨的办法,先把设计图按照百分比进行缩放,缩放到320左右的时候,再进行页面的书写。我们运用了rem,但是不是所有的div和元素都用rem,因为div运用rem的时候,转化为px会和之前换算的有点出入。没有办法,我们只是针对字体运用rem,div、padding、margin等还是用px作为单位。

这样做,垂直高度方面,大屏幕显示的内容多,小屏幕显示的内容少!且屏幕不同,有些地方间距会不同。因此,在有些时候,关键部分,产品要我们在所有尺寸屏幕都要显示一样,这样的话,我们这种布局就会有问题了!

改进后的做法

后来我们全站都用rem,包括padding,margin,height,width等。我们的做法是引进了如下js

!function(a, b, c) {
    function q() {
        var d = Math.min((o ? e[h]().width : f.innerWidth) / (a / b), c);
        d != p && (k.innerHTML = "html{font-size:" + d + "px!important;" + n + "}", p = d)
    }
    function r() {
        clearTimeout(l), l = setTimeout(q, 500)
    }
    var l, d = document,
        e = d.documentElement,
        f = window,
        g = "addEventListener",
        h = "getBoundingClientRect",
        i = "pageshow",
        j = d.head || d.getElementsByTagName("HEAD")[0],
        k = d.createElement("STYLE"),
        m = "text-size-adjust:100%;",
        n = "-webkit-" + m + "-moz-" + m + "-ms-" + m + "-o-" + m + m,
        o = h in e,
        p = null;
    a = a || 320, b = b || 16, c = c || 32, j.appendChild(k), d[g]("DOMContentLoaded", q, !1), "on" + i in f ? f[g](i, function(a) {
        a.persisted && r()
    }, !1) : f[g]("load", r, !1), f[g]("resize", r, !1), q()
}(
320, // 设置设计稿基准宽度
16, // 设置开发时的被除数(见HOW TO USE第4步) 在设计稿基准宽度为320时最好设置为16(在在设计稿基准宽度为其他值时等比放大,如640时设置为32等)。因为浏览器默认的值就是16,这样代码失效或尚未起效时,不会有布局问题
32 // 设置最大根元素font-size,请注意这是一个css像素值,而非物理像素值。它的作用是,当用户用非常宽的屏幕(pad、pc)访问页面时,不至于使得根元素的font-size超过这个值,使得布局非常难看。
);

这样,我们不管屏幕是什么尺寸,所有屏幕显示都是一样的。

借鉴其他网站,改进工作流程

在这里呢,我参考的是网易新闻的移动版网页!地址是http://3g.163.com/touch/news/subchannel/all

大家可以看到,不管是什么屏幕的尺寸,导航、字体等都会随着屏幕大小而伸缩。

下面我们一起来探索一下网易是如何做移动端页面布局的。

看下图:

enter image description here

enter image description here

通过上面的两幅图,我们可以看出,html根目录动态生成了一个font-size;body中定义了width是7.5rem;

那么他的font-size是根据什么计算的呢?

这就跟设计稿有关了,它的设计稿应该是基于iphone6来的,所以它的设计稿竖直放时的横向分辨率为750px,为了计算方便,取一个100px的font-size为参照,那么body元素的宽度就可以设置为width: 7.5rem,于是html的font-size=deviceWidth / 7.5。这个deviceWidth就是viewport设置中的那个deviceWidth。根据这个计算规则,可得出不同设备中html的font-size大小:

deviceWidth = 320,font-size = 320 / 7.5= 42.667px
deviceWidth = 375,font-size = 375 / 7.5 = 50px
deviceWidth = 414,font-size = 414 / 7.5 = 55.2px
deviceWidth = 500,font-size = 500 / 7.5= 66.667px

知道根据设计图有关,我们就可以根据设计图的尺寸来定义我们的font-size和body的width,举个例子:

设计图 640px ,我们定义body的width是6.4rem;font-size通过deviceWidth/6.4得到。

设计图750px ,我们定义body的width是7.5rem;font-size通过deviceWidth/7.5得到。

那么,我们在html根目录下面设置font-size;然后body中指定width之后,就可以轻松的根据设计图来书写css了。例如:设计图上面头部高度是60px;那么我们css中书写的高度是0.6rem

deviceWidth是如何计算的呢?

deviceWidth可以通过document.documentElement.clientWidth可视宽度来获取。那计算font-size的代码如下:

document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + 'px';

7.5只是举个例子,如果是640的设计稿,应该除以6.4

当然,网易还有其他逻辑,例如最大宽高1080等等。

附上部分网易代码:

var Dpr = 1, uAgent = window.navigator.userAgent;
var isIOS = uAgent.match(/iphone/i);
var isYIXIN = uAgent.match(/yixin/i);
var is2345 = uAgent.match(/Mb2345/i);
var ishaosou = uAgent.match(/mso_app/i);
var isSogou = uAgent.match(/sogoumobilebrowser/ig);
var isLiebao = uAgent.match(/liebaofast/i);
var isGnbr = uAgent.match(/GNBR/i);
function resizeRoot() {
    var wWidth = (screen.width > 0) ? (window.innerWidth >= screen.width || window.innerWidth == 0) ? screen.width : window.innerWidth : window.innerWidth, wDpr, wFsize;
    var wHeight = (screen.height > 0) ? (window.innerHeight >= screen.height || window.innerHeight == 0) ? screen.height : window.innerHeight : window.innerHeight;
    if (window.devicePixelRatio) {
        wDpr = window.devicePixelRatio;
    } else {
        wDpr = isIOS ? wWidth > 818 ? 3 : wWidth > 480 ? 2 : 1 : 1;
    }
    if (isIOS) {
        wWidth = screen.width;
        wHeight = screen.height;
    }
    // if(window.orientation==90||window.orientation==-90){
    //     wWidth = wHeight;
    // }else if((window.orientation==180||window.orientation==0)){
    // }
    if (wWidth > wHeight) {
        wWidth = wHeight;
    }
    wFsize = wWidth > 1080 ? 144 : wWidth / 7.5;
    wFsize = wFsize > 32 ? wFsize : 32;
    window.screenWidth_ = wWidth;
    if (isYIXIN || is2345 || ishaosou || isSogou || isLiebao || isGnbr) {//YIXIN 和 2345 这里有个刚调用系统浏览器时候的bug,需要一点延迟来获取
        setTimeout(function () {
            wWidth = (screen.width > 0) ? (window.innerWidth >= screen.width || window.innerWidth == 0) ? screen.width : window.innerWidth : window.innerWidth;
            wHeight = (screen.height > 0) ? (window.innerHeight >= screen.height || window.innerHeight == 0) ? screen.height : window.innerHeight : window.innerHeight;
            wFsize = wWidth > 1080 ? 144 : wWidth / 7.5;
            wFsize = wFsize > 32 ? wFsize : 32;
            // document.getElementsByTagName('html')[0].dataset.dpr = wDpr;
            document.getElementsByTagName('html')[0].style.fontSize = wFsize + 'px';
        }, 500);
    } else {
        // document.getElementsByTagName('html')[0].dataset.dpr = wDpr;
        document.getElementsByTagName('html')[0].style.fontSize = wFsize + 'px';
    }
    // alert("fz="+wFsize+";dpr="+window.devicePixelRatio+";UA="+uAgent+";width="+wWidth+";sw="+screen.width+";wiw="+window.innerWidth+";wsw="+window.screen.width+window.screen.availWidth);
}
resizeRoot();

通过以上代码可以防止手机横屏和竖屏产生的问题!

有兴趣的朋友也可以研究一下淘宝的做法,学习和查看别人的做法,也是一种进步!

Tags: 移动端rem前端

相关文章: