var adaptive = {}; (function (win, lib) { var doc = win.document; var docel = doc.documentelement; // 设备像素比 var devicepixelratio = win.devicepixelratio; // 我们设置的布局视口与理想视口的像素比 var dpr = 1; // viewport缩放值 var scale = 1; // 设置viewport function setviewport() { // 判断ios var isiphone = /iphone/gi.test(win.navigator.appversion); if (lib.scaletype === 2 && isiphone || lib.scaletype === 3) { dpr = devicepixelratio; } // window对象上增加一个属性,提供对外的布局视口与理想视口的值 win.devicepixelratiovalue = dpr; // viewport缩放值,布局视口缩放后刚好显示成理想视口的宽度,页面就不会过长或过短了 scale = 1 / dpr; // 获取已有的viewport var hasmetael = doc.queryselector('meta[name="viewport"]'); var metastr = 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'; if (dpr === 1) { metastr = 'width=device-width, '.concat(metastr); } if (!isiphone && dpr !== 1) { metastr = metastr.concat(', target-densitydpi=device-dpi'); } // 如果有,改变之 if (hasmetael) { hasmetael.setattribute('content', metastr); } // 如果没有,添加之 else { var metael = doc.createelement('meta'); metael.setattribute('name', 'viewport'); metael.setattribute('content', metastr); if (docel.firstelementchild) { docel.firstelementchild.appendchild(metael); } else { var containdiv = doc.createelement('div'); containdiv.appendchild(metael); docel.appendchild(containdiv); } } } var newbase = 100; lib.errdpr = 1; function setrem() { // 布局视口 // var layoutview = docel.clientwidth; 也可以 获取布局视口的宽度 var layoutview; if (lib.maxwidth) { layoutview = math.min(docel.getboundingclientrect().width, lib.maxwidth * dpr); } else { layoutview = docel.getboundingclientrect().width; } // 为了计算方便,我们规定 1rem === 100px设计图像素,我们切图的时候就能快速转换 // 计算一个值,使layout的总宽度为 (desinwidth/100) rem // 那么有计算公式:layoutview / newbase = desinwidth / 100 // newbase = 100 * layoutview / desinwidth // newbase = 介于50到200之间 // 如果 1rem === 1px 设计像素,newbase就介于0.5到2之间,由于很多浏览器有最小12px限制,这个时候就不能自适应了 newbase = 100 * layoutview / lib.desinwidth * (lib.errdpr || 1); docel.style.fontsize = newbase + 'px'; // rem基准值改变后,手动reflow一下,避免旋转手机后页面自适应问题 doc.body&&(doc.body.style.fontsize = lib.basefont / 100 + 'rem'); // 重新设置rem后的回调方法 lib.setremcallback&&lib.setremcallback(); lib.newbase = newbase; } var tid; lib.desinwidth = 1920; lib.basefont = 16; // 局部刷新的时候部分chrome版本字体过大的问题 lib.reflow = function() { docel.clientwidth; }; // 检查安卓下rem值是否显示正确 function checkrem() { if (/android/ig.test(win.navigator.appversion)) { var hidediv = document.createelement('p'); hidediv.style.height = '1px'; hidediv.style.width = '2.5rem'; hidediv.style.visibility = 'hidden'; document.body.appendchild(hidediv); var now = hidediv.offsetwidth; var right = lib.newbase * 2.5; if (math.abs(right / now - 1) > 0.05) { lib.errdpr = right / now; setrem(); } document.body.removechild(hidediv); } } lib.init = function () { // resize的时候重新设置rem基准值 // 触发orientationchange 事件时也会触发resize,故不需要再添加此事件了 win.addeventlistener('resize', function () { cleartimeout(tid); tid = settimeout(setrem, 300); }, false); // 浏览器缓存中读取时也需要重新设置rem基准值 win.addeventlistener('pageshow', function (e) { if (e.persisted) { cleartimeout(tid); tid = settimeout(setrem, 300); } }, false); // 设置body上的字体大小 if (doc.readystate === 'complete') { doc.body.style.fontsize = lib.basefont / 100 + 'rem'; checkrem(); } else { doc.addeventlistener('domcontentloaded', function (e) { doc.body.style.fontsize = lib.basefont / 100 + 'rem'; checkrem(); }, false); } setviewport(); // 设置rem值 setrem(); // html节点设置布局视口与理想视口的像素比 docel.setattribute('data-dpr', dpr); }; // 有些html元素只能以px为单位,所以需要提供一个接口,把rem单位换算成px lib.remtopx = function (remvalue) { return remvalue * newbase; }; })(window, adaptive); if (typeof module != 'undefined' && module.exports) { module.exports = adaptive; } else if (typeof define == 'function' && define.amd) { define(function() { return adaptive; }); } else { window.adaptive = adaptive; }