; (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'] = {}));