摘要:前言最近需要一款移動端的產(chǎn)品,當時需要趕工期,在參考了天貓的布局和手淘的布局方案后,決定選用。首先我們需要通過獲得的寬度,然后將寬度分為份,份為。當然這還是有一點點問題的因為這樣將不會是的滿屏了。
前言
最近需要一款移動端的產(chǎn)品,當時需要趕工期,在參考了天貓的flexbox布局和手淘的
rem布局方案后,決定選用libflexible。做完項目之后,稍有空閑時間,決定看看libflexible
如何實現(xiàn)動態(tài)設置根元素的字體,從而通過rem的方式改變其他元素大小
首先我們看一下flexible需要哪些屬性
;(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 = {});
在函數(shù)運行時,我們需要將windows對象注入,然后在看看windows下是否已經(jīng)存在lib(即是否已經(jīng)有
使用過flexible)了,注入完之后,我們依次獲得doc,docEl,metaEl,flexibleEl,其中metaEl
是為了判斷我們是否已經(jīng)有預設好的viewport,flexibleEl則是判斷我們已經(jīng)手動設置好dpr來避免
flexible庫動態(tài)設置dpr
if (metaEl) { console.warn("將根據(jù)已有的meta標簽來設置縮放比例"); var match = metaEl.getAttribute("content").match(/initial-scale=([d.]+)/); if (match) { scale = parseFloat(match[1]); dpr = parseInt(1 / scale); } }
如果metaEl存在的話,意味著頁面上存在形如的標簽,此時我們已經(jīng)明確了我們需要的縮放,不再需要flexible的介入,縮放值scale直接
使用預設的initial-scale,通過我們預設的的縮放,我們的layout viewport將會是 ideal viewport/scale,如果我們的initual-scale為1的話
且ideal為414px的話,我們的layout viewport將會是414px
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)); } } }
如果我們沒有設置初始的viewport但是有這樣的flexible自身的預設
那么我們將會有預設的dpr,此時flexible將根據(jù)我們預設的dpr通過scale=1/dpr的方式來計算出我們的縮放,進而影響layout viewport
的大小
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 { // 其他設備下,仍舊使用1倍的方案 dpr = 1; } scale = 1 / dpr; }
接下來,如果我們既沒有通過這種方式預設dpr,
也沒有通過的方式預設縮放,此時flexible開始根據(jù)
設備的dpr來動態(tài)計算縮放。對于非蘋果設備,flexible設置dpr為1,對于蘋果設備,iPhone3以下非retina屏,dpr為1
iPhone4-iPhone6為retina屏,dpr為2,iPhone6Plus為retina HD屏,dpr為3,由于flexible是一個專注于移動端
的解決方案,所以平板(包括iPad)或者桌面端的dpr都為1
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); } }
計算完縮放后,將獲取的dpr值設置到根元素上,這樣我們就可以通過以下方式:
.selector { width: 2rem; border: 1px solid #ffffd; } [data-dpr="1"] .selector { height: 32px; font-size: 14px; } [data-dpr="2"] .selector { height: 64px; font-size: 28px; } [data-dpr="3"] .selector { height: 96px; font-size: 42px; }
為不同dpr的屏幕設置不同的字體大小,字體之所以不用rem布局,是因為
我們不希望文本在Retina屏幕下變小,另外,我們希望在大屏手機上看到更多文本,以及,現(xiàn)在絕大多數(shù)的字體文件都自帶一些點陣尺寸,通常是16px和24px,所以我們不希望出現(xiàn)13px和15px這樣的奇葩尺寸。
同時當不存在metaEl時,flexible動態(tài)生成一條
的標簽,如果下存在元素(如等元素)那么,將meta標簽插入,如果沒有,就將meta標簽用一個div包裝,然后
通過document.write寫入到文檔中
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; }
好了,縮放和dpr都設置好了,下一步我們要設置根元素的font-size了,這樣我們可以通過rem的方式
適配不同屏幕。首先我們需要通過docEl.getBoundingClientRect().width獲得layout viewport的寬度,
然后將layout viewport寬度分為10份,1份為1rem。至于設置540px,是為了讓在ipad橫屏這種情況下瀏覽頁面,不至于因為拉伸適配后體驗太差。當然這還是有一點點問題的
因為這樣10rem將不會是ipad的滿屏了。當然這是移動端解決方案,并沒有考慮平板和桌面端
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);
接著當窗口發(fā)生變化或者頁面重新從緩存中載入時,我們都要重新設置尺寸
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); }
body上設置12 * dpr的font-size值,為了重置頁面中的字體默認值,不然沒有設置font-size的元素會繼承html上的font-size,變得很大。
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; }
最后,flexible提供了兩個工具函數(shù)px2rem和rem2px,這里就不在闡述了
總結看完flexible,實實在在的感受到rem布局的妙處,通過動態(tài)設置縮放系數(shù)的方式,
讓layout viewport與設計圖對應,極大地方便了重構,同時也避免了1px的問題,
然而略有遺憾的就是在安卓和ipad上的表現(xiàn)不佳了。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88232.html
摘要:一些方法不應該這樣不應該漫無目的地隨手拿起一分源碼,試圖去通讀。應該這樣精心挑選要閱讀的源碼項目。這最好是與你的編程語言你的工作內(nèi)容你的興趣所在相關的,這樣才能更切實地感受到閱讀源碼給你帶來的益處,更有動力繼續(xù)。 showImg(https://segmentfault.com/img/bVbcvmm?w=785&h=525); 怎么閱讀源碼 沒有經(jīng)驗的技術差底子薄的初級程序員,如何閱...
摘要:對于一個有追求的程序員來說必須讀源碼,當然閱讀源碼是一件令人頭疼的事。和差不多,想法一樣,但是和相比,搜索到的有價值結果不是很多,沒有的理想,還有一些來著百度知道。 對于一個有追求的程序員來說必須讀源碼,當然閱讀源碼是一件令人頭疼的事。閱讀別人的代碼遠比自己寫代碼要難。Linus 是Linux的早期作者,一句影響深遠的話是Read The Fucking Source Code(RTF...
閱讀 2902·2021-11-23 09:51
閱讀 1547·2021-11-15 11:36
閱讀 3006·2021-10-13 09:40
閱讀 1864·2021-09-28 09:35
閱讀 13040·2021-09-22 15:00
閱讀 1367·2019-08-29 13:56
閱讀 2924·2019-08-29 13:04
閱讀 2699·2019-08-28 18:06