移动端自适应方案

1.背景知识

首先是看几篇文章,了解viewport scale dpr 图片的显示精度问题 一像素显示问题, 缩放导致的像素适应问题 移动端的自适应问题
http://www.cnblogs.com/520yan...

http://www.cnblogs.com/520yan...

https://mp.weixin.qq.com/s?__...

https://github.com/amfe/artic...

1、图片精度问题

其实图片显示高清的问题,最理想的方案是根据dpr去加载不同精度的图片,但是一般这个工作效果不是很明显,直接显示精度大的图片就可以了,虽然在dpr是1的屏幕上会费流量、有点色差 但是完全可以忽略。
所以图片这个问题还好。

2、 1px显示的问题

1px显示的问题,利用缩放解决
一般设计给的设计稿都是针对iphone6的750px 1334px ,但是iphone6的设备独立像素是375px667px iphone6的dpr=2

所以如果我们把viewport设成375px的话,就无法显示设计稿中1px的元素。
所以为了显示1px,我们需要将viewport设成750px,然后设置scale=0.5,这样手机屏幕还是完整的显示页面,并且使得css中的px
和手机物理设备的px相同了。

3、scale缩放导致的像素适应问题

但是scale的缩放会影响原来的像素大小,比如在scale=1时,一个元素应该是12px 但是scale=0.5时,整体页面缩小了1倍,这个元素的大小应该是24px,才能和原来显示一样。

4、利用rem解决像素适应的问题,

在dpr=2的时候设html的font-size=100px,在dpr=1的时候设置font-size=50。然后需要在不同dpr下显示不同px的地方就可以以rem为单位进行设置。
那么为什么把dpr=2的时候设置font-size=100, 因为设计稿给的是iphone6 dpr=2的情况下的像素,所以根据设计稿换算起来比较简单,比如设计稿中font-size: 24px。我们可以直接写font-size:0.24rem。 这样在dpr=2的时候显示成24px 在dpr=1的时候显示成12px。

5、如何解决移动端的自适应问题

主要是移动端的屏幕尺寸比较多,如何在各种屏幕宽度下显示的更好,更一致问题。
比较简单的办法就是百分比或者flex。

以后深入研究下百分比和flex的使用。
比如750px,我们可以把所有元素flex的总和设成750px,比如左边flex 300 右边 flex450 就是 300比450的自适应。
百分比要注意的是他所设置的百分比 是父元素的宽度为基础的。

然后还要考虑的是高度的问题,高度怎么去适应。图片的话高度会随着宽度等比例缩放。

用rem解决自适应的问题,是个非常精确的解决方案,能够将高度和宽度都做到随着屏幕的宽度完全的等比缩放,但是缺点就是开发起来效率低点。来看看如何操作。

首先还是会根据dpr 来设置viewport的宽度和scale的缩放级别
然后设计成页面的宽度是10rem,
1rem = 页面宽度/10 = device-width * dpr /10;
以iphone6为例
1rem = 375 * 2 /10 = 75px;
所以设
html {
font-size = 75px;
}
然后把html加一个属性data-dpr = 2;

示例代码如下:

javascript方式,通过上面的公式,计算出基准值rem,然后写入样式,大概如下(代码参考自kimi的m-base模块)
var dpr, rem, scale;
var docEl = document.documentElement;
var fontEl = document.createElement('style');
var metaEl = document.querySelector('meta[name="viewport"]');

dpr = window.devicePixelRatio || 1;
rem = docEl.clientWidth * dpr / 10;
scale = 1 / dpr;

// 设置viewport,进行缩放,达到高清效果
metaEl.setAttribute('content', 'width=' + dpr * docEl.clientWidth + ',initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale + ',user-scalable=no');

// 设置data-dpr属性,留作的css hack之用
docEl.setAttribute('data-dpr', dpr);

// 动态写入样式
docEl.firstElementChild.appendChild(fontEl);
fontEl.innerHTML = 'html{font-size:' + rem + 'px!important;}';

// 给js调用的,某一dpr下rem和px之间的转换函数
window.rem2px = function(v) {
    v = parseFloat(v);
    return v * rem;
};
window.px2rem = function(v) {
    v = parseFloat(v);
    return v / rem;
};

window.dpr = dpr;
window.rem = rem;

这样的实现,就能够完全的将设计稿中的px对应成rem,并且能够根据屏幕的宽度进行自适应。
有两个问题:
第一个问题是设计稿到rem的转换降低开发效率
比如设计稿750px,1rem = 75px。 设计稿上的50px,我们需要计算出50/75 rem
第二个问题是 rem设置成device-width的10分之一,缩放引起的字体的大小变化就不能用rem来解决了
因为我们一般只是想在不同缩放下,一起缩放字体,而字体不需要自适应。
字体应该是在任何屏幕上字体都应该保持一致。

先说第二个问题:
这个就可以利用CSS实现
思路 因为已经在html上设置data=dpr

font-size: 16px;
[data-dpr="2"] input {
  font-size: 32px;
}

可以用sass写成一个mixin

@mixin dpr($property, $value) {
    & {
        #{$property}: $value / 2; /* no */
    }

    [data-dpr="2"] & {
        #{$property}: $value; /* no */
    }

    [data-dpr="3"] & {
        #{$property}: $value * 1.5; /* no */
    }
}

@mixin font-size($fontSize) {
    @include dpr(font-size, $fontSize);
}

这样用的地方可以这样写
@include font-size(52px);

再说第一个问题px到rem的转换问题
淘宝的rem库,lib-flexible
https://github.com/amfe/artic...
这篇文章里说了几种方法
有sublime的插件,有sass的处理函数,有gulp的插件,
我们现在都用webpack做开发,和打包,所以用一个webpack的插件px2rem-loader
这个插件可以实现我们直接写px 打包的时候自动转换成rem
CSS的loader中加入px2rem插件

const REM_UNIT = 75;
 let px2rem = `px2rem?remUnit=${REM_UNIT}&remPrecision=8&threeVersion=true`;
  return {
    css: generateLoaders([ 'css' , px2rem]),
    postcss: generateLoaders([ 'css' , px2rem]),
    less: generateLoaders([ 'css', px2rem , 'less' ]),
    sass: generateLoaders([ 'css', px2rem , 'sass?indentedSyntax' ]),
    scss: generateLoaders([ 'css', px2rem , 'sass' ]),
    stylus: generateLoaders([ 'css', px2rem , 'stylus' ]),
    styl: generateLoaders([ 'css', px2rem, 'stylus' ])
  }

猜你喜欢

转载自www.cnblogs.com/jlfw/p/12901815.html