; (function(win, lib) { var doc = win.document; var docEl = doc.documentElement; /** * 获取例如<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">的元素 * */ var metaEl = doc.querySelector('meta[name="viewport"]'); /** * 获取例如<meta name="flexible" content="initial-dpr=2,maximum-dpr=3" />的元素 * 其中initial-dpr会把dpr强制设置为给定的值,maximum-dpr会比较系统的dpr和给定的dpr,取最小值。注意:这两个参数只能选其一。 * */ var flexibleEl = doc.querySelector('meta[name="flexible"]'); // 屏幕可视区宽度叫设备独立像素,device independent pixels,简称dip或dp。屏幕可以显示的显示的实际像素数叫作物理像素。 // 定义设备像素比,像素比window.devicePixelRatio=物理像素/设备独立像素(dips) var dpr = 0; // 定义视口缩放比例 var scale = 0; // 定义setTimeout返回的值 var tid; // 获取或定义flexible对象 var flexible = lib.flexible || (lib.flexible = {}); // 若是存在视口的meta的标签 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) { // 若是存在弹性meta标签,获取content属性 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); // 判断是不是ios平台 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; } // 给html添加data-dpr属性 docEl.setAttribute('data-dpr', dpr); // 若是视口的meta标签不存在,则从新建立 if (!metaEl) { // 建立meta标签 metaEl = doc.createElement('meta'); // 给meta标签增长name属性,指定为视口 metaEl.setAttribute('name', 'viewport'); // 给meta标签设置content属性,指定最初的最大的缩放比例和禁止用户手动缩放 metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); // docEl.firstElementChild为head标签 判断有没有head标签 if (docEl.firstElementChild) { // 把meta标签加入到head标签中 docEl.firstElementChild.appendChild(metaEl); } else { // 若是不存在head标签,则建立一个div来包裹meta标签 var wrap = doc.createElement('div'); wrap.appendChild(metaEl); // 插入文档流 doc.write(wrap.innerHTML); } } // 刷新人 function refreshRem() { // 获取可视区域的宽度 var width = docEl.getBoundingClientRect().width; // 宽度除以设备像素比等于按比例缩放后的宽度,若是这个宽度大于540,那就设置宽度为540乘以设备像素比 // 就是设置屏幕的宽度极限 if (width / dpr > 540) { width = 540 * dpr; } // 定义1个rem等于宽度的十分之一 var rem = width / 10; // 给html标签绑定字号 字号等于一个rem docEl.style.fontSize = rem + 'px'; // 给flexiable对象增长rem属性 flexible.rem = win.rem = rem; } // 监听窗口变更 win.addEventListener('resize', // 这里运用了函数防抖 function() { // 清除tid clearTimeout(tid); // 建立tid,300毫秒后执行refreshRem tid = setTimeout(refreshRem, 300); }, false); // 监听页面展现事件 win.addEventListener('pageshow', function(e) { // event.persisted从缓存中获取时为true不然为false if (e.persisted) { clearTimeout(tid); tid = setTimeout(refreshRem, 300); } }, false); // 当dom加载完成时 if (doc.readyState === 'complete') { // 给body设置字号为12乘以设备像素比 doc.body.style.fontSize = 12 * dpr + 'px'; } else { // 当初始的 HTML 文档被彻底加载和解析完成以后 doc.addEventListener('DOMContentLoaded', function(e) { // 给body设置字号为12乘以设备像素比 doc.body.style.fontSize = 12 * dpr + 'px'; }, false); } // 刷新rem大小 refreshRem(); // 给flexible对象增长属性 flexible.dpr = win.dpr = dpr; flexible.refreshRem = refreshRem; // rem转为px flexible.rem2px = function(d) { // 参数乘以一个rem表明的px值 // parseFloat() 函数可解析一个字符串,并返回一个浮点数。该函数指定字符串中的首个字符是不是数字。若是是,则对字符串进行解析,直到到达数字的末端为止,而后以数字返回该数字,而不是做为字符串。 var val = parseFloat(d) * this.rem; // 若是参数为字符串而且含有rem字符串 if (typeof d === 'string' && d.match(/rem$/)) { // 拼装px val += 'px'; } return val; } //px转为rem flexible.px2rem = function(d) { // 参数除以rem的长度 var val = parseFloat(d) / this.rem; // 若是参数为字符串而且含有px字符串 if (typeof d === 'string' && d.match(/px$/)) { val += 'rem'; } return val; } })(window, window['lib'] || (window['lib'] = {}));