淘寶實用lib-flexible來適配各類大小的屏幕

####淘寶實用lib-flexible來適配各類大小的屏幕,如今來說講適配的原理html

  1. 使用方法
<script src="src/lib-flexible.js"></script>
複製代碼
  1. 源碼解析
;(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 = {});
   /*將根據已有的meta標籤來設置縮放比例*/
    if (metaEl) {
        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));
            }
        }
    }
    /*當原先沒有設置過meta,以及縮放比例
    * iphone手機根據2,3屏幕處理
    * 其餘設備下,仍舊使用1倍的方案  獲得dpr和scale的值
    * */
    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;
    }
    /*設置html的data-dpr的值*/
    docEl.setAttribute('data-dpr', dpr);
    /*
    *scale
    * 查詢有沒有meta屬性,沒有的狀況下加上 <meta content='initial-scale= scale, maximum-scale=scale, minimum-scale=scale, user-scalable=no/> * */ 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); } } /* * 這個width跟dpr有關係 例如iphone5 dpr爲2 獲得的屏幕的寬爲640px * 例如iphone6 plus dpr爲3 獲得的屏幕的寬爲1242px * */ function refreshRem(){ var width = docEl.getBoundingClientRect().width; //注意這裏,這裏是適配手機的一個具體的參數,相對大於540的就不適用了 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(); /*rem轉px px轉rem*/ 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. 先來了解一點關於viewport的知識,一般咱們採用以下代碼設置viewport:
  2. <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  3. 這樣整個網頁在設備內顯示時的頁面寬度就會等於設備邏輯像素大小,也就是device-width。這個device-width的計算公式爲:

設備的物理分辨率/(devicePixelRatio * scale),在scale爲1的狀況下,device-width = 設備的物理分辨率/devicePixelRatio 。前端

devicePixelRatio稱爲設備像素比,每款設備的devicePixelRatio都是已知,而且不變的,目前高清屏,廣泛都是2,不過還有更高的,好比2.5, 3 等,我魅族note的手機的devicePixelRatio就是3。淘寶觸屏版佈局的前提就是viewport的scale根據devicePixelRatio動態設置:android

  1. 這麼作目的固然是爲了保證頁面的大小與設計稿保持一致了,好比設計稿若是是750的橫向分辨率,那麼實際頁面的device-width,以iphone6來講,也等於750,這樣的話設計稿上標註的尺寸只要除以某一個值就可以轉換爲rem了。經過js設置viewport的方法以下:
  2. 接下來要解決的問題是,元素的尺寸該如何計算,好比說設計稿上某一個元素的寬爲150px,換算成rem應該怎麼算呢?這個值等於設計稿標註尺寸/該設計稿對應的html的font-size。拿淘寶來講的,他們用的設計稿是750的,因此html的font-size就是75,若是某個元素時150px的寬,換算成rem就是150 / 75 = 2rem。總結下淘寶的這些作法:
  3. 最後還有一個狀況要說明,跟網易同樣,淘寶也設置了一個臨界點,當設備豎着時橫向物理分辨率大於1080時,html的font-size就不會變化了,緣由也是同樣的,分辨率已經能夠去訪問電腦版頁面了。
  4. https://github.com/amfe/lib-flexible

如何與設計協做

  1. 第一步,視覺設計階段,設計師按寬度750px(iphone 6)作設計稿,除圖片外全部設計元素用矢量路徑來作。設計定稿後在750px的設計稿上作標註,輸出標註圖。同時等比放大1.5倍生成寬度1125px的設計稿,在1125px的稿子裏切圖。
  2. 第二步,輸出兩個交付物給開發工程師:一個是程序用到的@3x切圖資源,另外一個是寬度750px的設計標註圖。
  3. 第三步,開發工程師拿到750px標註圖和@3x切圖資源,完成iPhone 6(375pt)的界面開發。此階段不能用固定寬度的方式開發界面,得用自動佈局(auto layout),方便後續適配到其它尺寸。
  4. 第四步,適配調試階段,基於iPhone 6的界面效果,分別向上向下調試iPhone 6 plus(414pt)和iPhone 5S及如下(320pt)的界面效果。由此完成大中小三屏適配。

####參考 前端開發博客(沒有找到名字的人)git

相關文章
相關標籤/搜索