移动端适配--flexible.js
引言:
H5适配一直是一个比较普遍的问题,很多文章都会讲,最近开发了一个H5的项目使用了一下淘宝的 flexible.js,写一篇文章自己总结一下。
一、背景介绍:
Flexible.js是淘宝公开的一种移动端适配方案,用来解决H5开发中的各个机型适配问题,是一种比较成熟的适配方案。
二、使用方法:
在html头部引入flexible.js,最好放在最头部,重构时使用rem替代px像素即可,flexible会做好所有适配。换算关系为1rem对应1/10设计尺寸,如ipone6设计尺寸为750px,那么重构时宽度对应的就是10rem。
<script type="text/javascript" src="../../js/flexible.js"></script>
三、Flexible.js原理:
比较短,直接上代码:
;(function(win, lib) {
var doc = win.document;
var docEl = doc.documentElement;
var metaEl = doc.querySelector('meta[name="viewport"]');
var flexibleEl = doc.querySelector('meta[name="flexible"]');
var dpr = 0;
var scale = 0;
var tid;
var flexible = lib.flexible || (lib.flexible = {});
if (metaEl) {
console.warn('将根据已有的meta标签来设置缩放比例');
var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
if (match) {
scale = parseFloat(match[1]);
dpr = parseInt(1 / scale);
}
} else if (flexibleEl) {
var content = flexibleEl.getAttribute('content');
if (content) {
var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
if (initialDpr) {
dpr = parseFloat(initialDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
if (maximumDpr) {
dpr = parseFloat(maximumDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
}
}
if (!dpr && !scale) {
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3;
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
dpr = 2;
} else {
dpr = 1;
}
} else {
// 其他设备下,仍旧使用1倍的方案
dpr = 1;
}
scale = 1 / dpr;
}
docEl.setAttribute('data-dpr', dpr);
if (!metaEl) {
metaEl = doc.createElement('meta');
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl);
} else {
var wrap = doc.createElement('div');
wrap.appendChild(metaEl);
doc.write(wrap.innerHTML);
}
}
function refreshRem(){
var width = docEl.getBoundingClientRect().width;
if (width / dpr > 540) {
width = 540 * dpr;
}
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
win.addEventListener('resize', function() {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}, false);
win.addEventListener('pageshow', function(e) {
if (e.persisted) {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}
}, false);
if (doc.readyState === 'complete') {
doc.body.style.fontSize = 12 * dpr + 'px';
} else {
doc.addEventListener('DOMContentLoaded', function(e) {
doc.body.style.fontSize = 12 * dpr + 'px';
}, false);
}
refreshRem();
flexible.dpr = win.dpr = dpr;
flexible.refreshRem = refreshRem;
flexible.rem2px = function(d) {
var val = parseFloat(d) * this.rem;
if (typeof d === 'string' && d.match(/rem$/)) {
val += 'px';
}
return val;
}
flexible.px2rem = function(d) {
var val = parseFloat(d) / this.rem;
if (typeof d === 'string' && d.match(/px$/)) {
val += 'rem';
}
return val;
}
})(window, window['lib'] || (window['lib'] = {}));
可以看出其核心就是两段代码:
1.当用户没有设置viewport的时候调整viewport:
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
viewport(视口)的调整逻辑是根据dpr(window.devicePixelRatio,设备像素比)来调整。
以iphone6为例:
dpr = 2,sale = 1/dpr = 0.5,也是就是说flexible会将视口缩放到原来的0.5倍,这样做的好处是能让逻辑像素与物理像素相等,避免出现1px在retina屏幕上显示过粗的现象(移动端经典的1px问题)。
2.设置根元素字体大小:
function refreshRem(){
var width = docEl.getBoundingClientRect().width;
if (width / dpr > 540) {
width = 540 * dpr;
}
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
rem是根据根元素来做渲染的,所以flexible直接调整根元素的大小就可以做到适配了,调整的思路是根据视口宽度(document.doumentElement.getBoundingClientRect().width)做调整(ps:viewport还分layout viewport和 visual viewport,不引申)。
四、注意事项&&总结:
1.当用户不设置viewport的时候,flexible.js会根据dpr默认设置viewport,这里的好处已经讲到,在精准显示1px像素的时候比较准确。但是也会带来部分问题,如引用第三方插件并且插件本身用px像素设置,这个时候就会带来缩放显示问题,所以如果有这种需求的话建议自己权衡,个人建议可能使用第三方的业务自行设置viewport,1px问题可以用其他手段处理,一般没有高保真的需求本身也没有必要。
2.flexible对字体的设置不推荐使用rem单位,建议使用px像素,适配根据dpr来做。原因简单看了下主要是网页可能会使用点阵字体,一般点阵大小是16、24的,调整后的字体大小可能不大标准,在字体点阵上显示会比较模糊,不细究了,有时间再研究补充。
总结:移动端适配核心就是将像素rem化,之后根据视口调整根元素达到适配的效果。
移动端适配--flexible.js的更多相关文章
- 移动端适配flexible.js
npm install lib-flexible --save npm install px2rem-loader --save-dev
- vue.js移动端配置flexible.js
前言 最近在用vue做移动端项目,网上找了一些移动端适配的方案,个人觉得手淘团队flexible.js还是比较容易上手,在这里做下总结. 主体 flexible.js适配方案采用rem布局,根据屏幕分 ...
- vue脚手架搭建移动端项目--flexible.js
通过命令行 node -v 查看是否安装node环境 在 nodejs 和 webpack已安装的前提下,随便一个文件夹下,输入命令行 npm install vue-cli -g 安装完成后,通过 ...
- vue-cli配置移动端自适应flexible.js
第一部分:项目中引入lib-flexible 一.项目中安装lib-flexible npm install lib-flexible --save-dev 二.在项目入口文件main.js中引入li ...
- 淘宝适配 flexible.js
1.引入 阿里cdm文件,也可以自己下载下来引用,不需要在添加<meta name="viewport"">标签了 <script src=" ...
- 【前端开发】移动端适配方案js,rem单位转换,640设计稿20px=1rem
! function() { var style = document.createElement("STYLE"), docEl = document.documentEleme ...
- css样式重置 移动端适配
css 默认样式重置 @charset "utf-8"; *{margin:0;padding:0;} img {border:none; display:block;} em, ...
- 从flexible.js引入高德地图谈起的移动端适配
曾几何时,前端还仅仅是PC端的.随着移动时代的兴起,h5及css3的推陈出新.前端的领域慢慢的由传统的pc端转入了移动端,这也导致了前端这一职业在风口的一段时间出尽了风头. 从开始的惶恐和无从下手,慢 ...
- 移动端适配方案 flexible.js
前言 移动端适配一直以来都是前端开发中不可或缺的重要组成部分,如果没有了它,那么你做出来的页面极有可能会出现各种意外(写出来的页面与设计稿之间的差别).所有我们得找到一种相对来说让人比较满意的解决方案 ...
随机推荐
- Python-Django-BMS-增删改查
无名分组 有名分组 反向解析 更改路由后不影响,动态传值 locals()传参 queryset.update() 自定义过滤器 {{forloop.counter}} new.authors.add ...
- 在python中使用print()时,raw write()返回无效的长度:OSError: raw write() returned invalid length 254 (should have been between 0 and 127)
写出一个不是code的bug,很烦恼,解决了挺长时间,都翻到外文来看,不过还是解决了,只尝试了一种简单可观的方法,希望对大家有用 我正在使用Django与Keras(tensorflow)来训练一个模 ...
- n 个骰子的点数
把 n 个骰子仍在地上,求点数和为 s 的概率. java: public List<Map.Entry<Integer, Double>> dicesSum(int n) { ...
- php获取两个时间戳之间相隔多少天多少小时多少分多少秒
/** * 返回两个时间的相距时间,*年*月*日*时*分*秒 * @param int $one_time 时间一 * @param int $two_time 时间二 * @param int $r ...
- tensorflow建造神经网络-【老鱼学tensorflow】
上次我们添加了一个add_layer函数,这次就要创建一个神经网络来预测/拟合相应的数据. 下面我们先来创建一下虚拟的数据,这个数据为二次曲线数据,但同时增加了一些噪点,其图像为: 相应的创建这些伪造 ...
- UVA 548 Tree 建树
题意: 输入中序和后序的权值,输出哪个叶子使它到根的路径上权和最小. 思路: 输入后建树,然后dfs求最小的叶子. #include<iostream> #include<cstdi ...
- 使用CSS达到文字首尾对齐效果
在制作表单的时候经常会遇到需要不同个数的文字首尾对齐,比如: <span>姓名:</span> <span>联系方式:</span> 姓名: 联系方式: ...
- Jmeter学习系列----1 环境搭建
注:在安装Jmeter之前,请先检查下电脑有没有装JDK:开始->运行->然后输入cmd->进入命令行界面,输入java -version , 出现以下信息就是此电脑已安装了JDK. ...
- debian包的补丁管理工具:quilt
最近项目是改pam软件包,给里面添加一些功能.其中遇到了更改后,代码提交方式的问题.这里转载的文章介绍了使用quilt管理补丁的详细方法: 转自:http://blog.csdn.net/fmddlm ...
- 8. 环境变量_数据库_mongoose的基本使用_模型对象的CRUD
1. 环境变量 系统环境(cmd)使用的变量/命令 能够让我们在cmd环境下运行指定的程序 用户环境变量 path(我们一般设置这个) 系统环境变量 path 过程: 当我们在cmd中输入一个指令 先 ...