移動端適配,h5網頁,手機端適配兼容方案.能夠顯示真實的1px邊框和12px字體大小,dpr淺析

之前寫移動端都是用這段JS解決.css

(function (doc, win) {
    // 分辨率Resolution適配
    var docEl = doc.documentElement,
            resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
            recalc = function () {
                var clientWidth = docEl.clientWidth;
                if (!clientWidth) return;
                if (clientWidth >= 750) {
                    docEl.style.fontSize = 100 + 'px';
                }else{docEl.style.fontSize = 100 * (clientWidth / 750) + 'px';}
            }
    // Abort if browser does not support addEventListener
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    recalc();
})(document, window);

JS中設計稿的大小能夠隨便改,我這裏用的設計稿都是750的,將750尺寸下,根元素font-size大小設置成100px,用這個JS能夠實現頁面隨根元素的font-size大小而改變,也就是rem寫法.當設計稿中元素大小爲100px時候,只要在css中設置成1rem就能夠.計算很方便,這樣寫確實簡單.算法

但這個JS有一些很難受的弊端,其一在如今iphone和其它手機中,dpr值都爲2或者3,這樣會出現移動端1px這個不是1px的難題,會是2px 3px的大小.這樣會致使給一個文字加邊框文字會塌下去的問題.瀏覽器

字體大小在dpr=2的iphone設備只能設置到24px,原理以下375*24/750=12,瀏覽器最小設置字體大小爲12.ipone5的真實大小是375pt.也就是真實設計稿750px的一半大.sass

dpr=3的設備也只能設置到12*750/414=21.74px.因此弊端很多.ipone6plus的真實大小是414pt.app

不懂 dpr pt px的能夠去網上問問,理解就能夠.iphone

前段時間看到網上有個hotcss解決方案,我研究了一下代碼.代碼以下(作了簡單的修改,緣由下文中有):異步

(function( window , document ){

    'use strict';

    //給hotcss開闢個命名空間,別問我爲何,我要給你準備你會用到的方法,省得用到的時候還要本身寫。
    var hotcss = {};

    (function() {
        //根據devicePixelRatio自定計算scale
        //能夠有效解決移動端1px這個世紀難題。
        var viewportEl = document.querySelector('meta[name="viewport"]'),
            hotcssEl = document.querySelector('meta[name="hotcss"]'),
            dpr = window.devicePixelRatio || 1,
            maxWidth = 750,//最大顯示尺寸
            designWidth = 0;

        dpr = dpr >= 3 ? 3 : ( dpr >=2 ? 2 : 1 );

        //容許經過自定義name爲hotcss的meta頭,經過initial-dpr來強制定義頁面縮放
        if (hotcssEl) {
            var hotcssCon = hotcssEl.getAttribute('content');
            if (hotcssCon) {
                var initialDprMatch = hotcssCon.match(/initial\-dpr=([\d\.]+)/);
                if (initialDprMatch) {
                    dpr = parseFloat(initialDprMatch[1]);
                }
                var maxWidthMatch = hotcssCon.match(/max\-width=([\d\.]+)/);
                if (maxWidthMatch) {
                    maxWidth = parseFloat(maxWidthMatch[1]);
                }
                var designWidthMatch = hotcssCon.match(/design\-width=([\d\.]+)/);
                if (designWidthMatch) {
                    designWidth = parseFloat(designWidthMatch[1]);
                }
            }
        }

        document.documentElement.setAttribute('data-dpr', dpr);
        hotcss.dpr = dpr;

        document.documentElement.setAttribute('max-width', maxWidth);
        hotcss.maxWidth = maxWidth;

        if( designWidth ){
            document.documentElement.setAttribute('design-width', designWidth);
            hotcss.designWidth = designWidth;
        }

        var scale = 1 / dpr,
            content = 'width=device-width, initial-scale=' + scale + ', minimum-scale=' + scale + ', maximum-scale=' + scale + ', user-scalable=no';

        if (viewportEl) {
            viewportEl.setAttribute('content', content);
        } else {
            viewportEl = document.createElement('meta');
            viewportEl.setAttribute('name', 'viewport');
            viewportEl.setAttribute('content', content);
            document.head.appendChild(viewportEl);
        }

    })();

    hotcss.px2rem = function( px , designWidth ){
        //預判你將會在JS中用到尺寸,特提供一個方法助你在JS中將px轉爲rem。就是這麼貼心。
        if( !designWidth ){
            //若是你在JS中大量用到此方法,建議直接定義 hotcss.designWidth 來定義設計圖尺寸;
            //不然能夠在第二個參數告訴我你的設計圖是多大。
            designWidth = parseInt(hotcss.designWidth , 10);
        }

        return parseInt(px,10)*750/designWidth/100;
    }

    hotcss.rem2px = function( rem , designWidth ){
        //新增一個rem2px的方法。用法和px2rem一致。
        if( !designWidth ){
            designWidth = parseInt(hotcss.designWidth , 10);
        }
        //rem可能爲小數,這裏再也不作處理了
        return rem*100*designWidth/750;
    }

    hotcss.mresize = function(){
        //對,這個就是核心方法了,給HTML設置font-size。
        var innerWidth = document.documentElement.getBoundingClientRect().width || window.innerWidth;

        if( hotcss.maxWidth && (innerWidth/hotcss.dpr > hotcss.maxWidth) ){
            innerWidth = hotcss.maxWidth*hotcss.dpr;
        }

        if( !innerWidth ){ return false;}

        document.documentElement.style.fontSize = ( innerWidth*100/750 ) + 'px';//設計尺寸750 根元素爲100px  便於計算

        hotcss.callback && hotcss.callback();

    };

    hotcss.mresize(); 
    //直接調用一次

    window.addEventListener( 'resize' , function(){
        clearTimeout( hotcss.tid );
        hotcss.tid = setTimeout( hotcss.mresize , 33 );
    } , false ); 
    //綁定resize的時候調用

    window.addEventListener( 'load' , hotcss.mresize , false ); 
    //防止不明緣由的bug。load以後再調用一次。


    setTimeout(function(){
        hotcss.mresize(); 
        //防止某些機型怪異現象,異步再調用一次
    },333)

    window.hotcss = hotcss; 
    //命名空間暴露給你,控制權交給你,想怎麼調怎麼調。


})( window , document );

這樣寫出來的方案就考慮到了dpr值的影響,以上問題均可以解決掉,他們的CSS是用sass實時去編譯計算的,函數

寬高這麼寫width:px2rem(182);height:px2rem(53);

下邊這個函數就是用來解決這個算法的.測試

@function px2rem( $px ){
@return $px*320/$designWidth/20 + rem;
}

他的JS我稍微作了修改,由於老去寫px2rem()這個方法煩的很,因此我把裏邊計算根元素字體大小這句改爲以下字體

document.documentElement.style.fontSize = ( innerWidth*100/750 ) + 'px';//設計尺寸750 根元素爲100px  便於計算

 這樣作的緣由以下,個人設計稿一直都是750px,在這個尺寸下我將根元素字體大小設置成100px,這樣我設計稿上的元素高是98px的時候,我直接設置成0.98rem;這樣簡單的計算一下,速度很快,也不會去寫px2rem()這個方法;

若是寫個簡單活動頁面,也能夠不用sass 老去監聽編譯,測試也麻煩.直接口算簡單易用.

若是你的設計稿是720,這句話應該爲

document.documentElement.style.fontSize = ( innerWidth*100/720 ) + 'px';
相關文章
相關標籤/搜索