乐趣区

续命之移动适配

最近看了好多移动适配的资料,整理了一下
以作后续开发少出 bug(哈哈~)
移动端布局,为了适配各种大屏手机,目前最好用的方案莫过于使用相对单位 rem。
基于 rem 的原理,我们要做的就是:
针对不同手机屏幕尺寸和 dpr 动态的改变根节点 html 的 font-size 大小 (基准值)。
这里我们提取了一个公式(rem 表示基准值)
rem = document.documentElement.clientWidth * dpr / 10

如何转换成 rem 单位呢?
公式如下:
rem = px / 基准值;

rem 方案一

首先,先说一个常识,浏览器的默认字体高都是 16px。
使用 % 单位方便使用
css 中的 body 中先全局声明 font-size=62.5%,这里的 % 的算法和 rem 一样。
因为 100%=16px,1px=6.25%,所以 10px=62.5%,
这是的 1rem=10px,所以 12px=1.2rem。px 与 rem 的转换通过 10 就可以得来,很方便了吧!
使用方法
注意,rem 是只相对于根元素 htm 的 font-size,即只需要设置根元素的 font-size,其它元素使用 rem 单位设置成相应的百分比即可;
例子:


一般情况下,是这样子使用的


移动端做适配的时候,可以使用这样的方法

方案二 js 中 rem 是怎么用的

首先得让文字和标签的大小随着屏幕的尺寸做变化 等比缩放,然后在把计算出的值赋给 html


这样当前窗口的字体就能获取到了,然后我们再设置窗口大小改变的情况,其实也就是加一个窗口改变的监听事件 onresize。发生了 onresize,就重新计算该窗口下根目录字体的大小。

方案三 从 dpr 维度的适配

上文也提到了 dpr 那么什么是 dpr 呢 通俗点讲就是
花了 200px 的长宽来渲染 CSS 里面定义的 100px 的长宽
而样式 pixels 和设备 pixels 的比值,就是 dpr,即 Device Pixel Ratio
<!DOCTYPE html>
<html lang=”en”>
<head>

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
  .box1{
      height: 5rem;
      width: 5rem;
      background-color:red;
  }
</style>

</head>
<body>

<div class="box1"></div>

</body>
<script>
var dpr = window.devicePixelRatio;// 当前显示设备的物理像素分辨率与 CSS 像素分辨率的比值
var meta = document.createElement(‘meta’);

// dpr
meta.setAttribute(‘content’, ‘initial-scale=’ + 1 / dpr + ‘, maximum-scale=’ + 1 / dpr + ‘, minimum-scale=’ + 1 / dpr + ‘, user-scalable=no’);
document.getElementsByTagName(‘head’)[0].appendChild(meta);

// rem
document.addEventListener(‘DOMContentLoaded’, function (e) {

document.getElementsByTagName('html')[0].style.fontSize = window.innerWidth / 10 + 'px';

}, false);
</script>
</html>
为了防止全局变量污染或者覆盖他人的变量,可封装成模块再使用。

方案四 lib-flexible 适配

lib-flexible 是一个制作 H5 适配的开源库
你可以直接使用阿里 CDN
<script src=”http://g.tbcdn.cn/mtb/lib-fle…{{version}}/??flexible_css.js,flexible.js”></script>
将代码中的 {{version}} 换成对应的版本号 0.3.4。
详情:https://github.com/amfe/artic…

方案五:
与方案三有一曲同工之妙,写得比较全
javascript 方式,通过上面的公式,计算出基准值 rem,然后写入样式,大概如下

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;

最后 字体大小问题

既然上面的方案会使得页面缩放 (scale),
对于字体缩放问题,设计师原本的要求是这样的:任何手机屏幕上字体大小都要统一,所以我们针对不同的分辨率 (dpr 不同),会做如下处理:
font-size: 16px;
[data-dpr=”2″] input {
font-size: 32px;
}
(注意,字体不可以用 rem,误差太大了,且不能满足任何屏幕下字体大小相同)
为了方便,我们也会用 less 写一个 mixin:

.px2px(@name, @px){
@{name}: round(@px / 2) * 1px;
[data-dpr=”2″] & {
@{name}: @px * 1px;
}
// for mx3
[data-dpr=”2.5″] & {
@{name}: round(@px 2.5 / 2) 1px;
}
// for 小米 note
[data-dpr=”2.75″] & {
@{name}: round(@px 2.75 / 2) 1px;
}
[data-dpr=”3″] & {
@{name}: round(@px / 2 3) 1px
}
// for 三星 note4
[data-dpr=”4″] & {
@{name}: @px * 2px;
}
}

退出移动版