移动端适配--flexible.js
引言:
H5適配一直是一個比較普遍的問題,很多文章都會講,最近開發(fā)了一個H5的項目使用了一下淘寶的 flexible.js,寫一篇文章自己總結(jié)一下。
一、背景介紹:
Flexible.js是淘寶公開的一種移動端適配方案,用來解決H5開發(fā)中的各個機(jī)型適配問題,是一種比較成熟的適配方案。
二、使用方法:
在html頭部引入flexible.js,最好放在最頭部,重構(gòu)時使用rem替代px像素即可,flexible會做好所有適配。換算關(guān)系為1rem對應(yīng)1/10設(shè)計尺寸,如ipone6設(shè)計尺寸為750px,那么重構(gòu)時寬度對應(yīng)的就是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('將根據(jù)已有的meta標(biāo)簽來設(shè)置縮放比例');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 {// 其他設(shè)備下,仍舊使用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.當(dāng)用戶沒有設(shè)置viewport的時候調(diào)整viewport:
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');viewport(視口)的調(diào)整邏輯是根據(jù)dpr(window.devicePixelRatio,設(shè)備像素比)來調(diào)整。
以iphone6為例:
dpr = 2,sale = 1/dpr = 0.5,也是就是說flexible會將視口縮放到原來的0.5倍,這樣做的好處是能讓邏輯像素與物理像素相等,避免出現(xiàn)1px在retina屏幕上顯示過粗的現(xiàn)象(移動端經(jīng)典的1px問題)。
2.設(shè)置根元素字體大小:
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是根據(jù)根元素來做渲染的,所以flexible直接調(diào)整根元素的大小就可以做到適配了,調(diào)整的思路是根據(jù)視口寬度(document.doumentElement.getBoundingClientRect().width)做調(diào)整(ps:viewport還分layout viewport和 visual viewport,不引申)。
四、注意事項&&總結(jié):
1.當(dāng)用戶不設(shè)置viewport的時候,flexible.js會根據(jù)dpr默認(rèn)設(shè)置viewport,這里的好處已經(jīng)講到,在精準(zhǔn)顯示1px像素的時候比較準(zhǔn)確。但是也會帶來部分問題,如引用第三方插件并且插件本身用px像素設(shè)置,這個時候就會帶來縮放顯示問題,所以如果有這種需求的話建議自己權(quán)衡,個人建議可能使用第三方的業(yè)務(wù)自行設(shè)置viewport,1px問題可以用其他手段處理,一般沒有高保真的需求本身也沒有必要。
2.flexible對字體的設(shè)置不推薦使用rem單位,建議使用px像素,適配根據(jù)dpr來做。原因簡單看了下主要是網(wǎng)頁可能會使用點(diǎn)陣字體,一般點(diǎn)陣大小是16、24的,調(diào)整后的字體大小可能不大標(biāo)準(zhǔn),在字體點(diǎn)陣上顯示會比較模糊,不細(xì)究了,有時間再研究補(bǔ)充。
總結(jié):移動端適配核心就是將像素rem化,之后根據(jù)視口調(diào)整根元素達(dá)到適配的效果。
轉(zhuǎn)載于:https://www.cnblogs.com/DevinnZ/p/8683902.html
總結(jié)
以上是生活随笔為你收集整理的移动端适配--flexible.js的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 天猫上线“商家售后服务评价”功能,消费者
- 下一篇: JDK中的Atomic包中的类及使用