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);html
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl);
} else {
var containDiv = doc.createElement('div');
containDiv.appendChild(metaEl);
docEl.appendChild(containDiv);
}
}
}android
var newBase = 100;
lib.errDpr = 1;chrome
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設計圖像素,咱們切圖的時候就能快速轉換
// 有人問,爲何不讓1rem === 1px設計像素呢?
// 設計圖通常是640或者750px
// 佈局視口通常是320到1440
// 計算一個值,使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 = 750;
lib.baseFont = 28;
// 局部刷新的時候部分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;
}瀏覽器