移动端rem适配

314 阅读2分钟

1、适配代码

!(function (w, d, options) {
    var timeout;
    var doc = d.documentElement;
    var dpr = w.devicePixelRatio || 1;
    var config = Object.assign(
        {
            ui: 750, // 设计尺寸
            base: 375, // 基准尺寸
            rootValue: 75, // rootValue(postcss-pxtorem) 75px
            minvw: 320, // 最小适配尺寸 320px
        },
        options || {}
    );
    // 设置maxvw最大适配尺寸
    config.maxvw || (config.maxvw = config.ui);

    // set dpr
    doc.setAttribute("data-dpr", dpr);
    window.dpr = dpr;

    function hairlines() {
        // hairlines .5px 支持
        if (dpr >= 2) {
            var fakeBody = d.createElement("body");
            var testElement = d.createElement("div");
            testElement.style.border = ".5px solid transparent";
            fakeBody.appendChild(testElement);
            doc.appendChild(fakeBody);
            if (testElement.offsetHeight === 1) {
                doc.classList.add("hairlines");
            }
            doc.removeChild(fakeBody);
        }
    }

    function setHtmlFontSize() {
        var vw = doc.getBoundingClientRect().width;
        // 计算当前适配计算尺寸
        var remvw = vw > config.maxvw ? config.maxvw : vw < config.minvw ? config.minvw : vw;
        // 计算公式: config.rootValue / (config.ui/config.base) * remvw / config.base
        var fontSize = (config.rootValue * remvw) / config.ui;
        doc.style.fontSize = fontSize + "px";
        
        // 为js计算提供数据
        w.__rem__ =  { fontSize : fontSize, remvw : remvw, ui : config.ui, base : config.base };
    }
    // ======================初始化============
    // init
    setHtmlFontSize();
    // hairlines .5px 支持
    if (dpr >= 2) {
        var fakeBody = d.createElement("body");
        var testElement = d.createElement("div");
        testElement.style.border = ".5px solid transparent";
        fakeBody.appendChild(testElement);
        doc.appendChild(fakeBody);
        if (testElement.offsetHeight === 1) {
            doc.classList.add("hairlines");
        }
        doc.removeChild(fakeBody);
    }
    // ======================监听============
    // resize
    window.addEventListener(
        "resize",
        function (e) {
            // 延迟200ms
            clearTimeout(timeout);
            timeout = setTimeout(setHtmlFontSize, 200);
        },
        false
    );
    // pageshow
    window.addEventListener(
        "pageshow",
        function (e) {
            if (e.persisted) {
                clearTimeout(timeout);
                timeout = setTimeout(setHtmlFontSize, 200);
            }
        },
        false
    );
    // ===============处理微信设置字体导致页面乱码问题(非微信可以删除)=======================
    if (typeof WeixinJSBridge == "object" && typeof WeixinJSBridge.invoke == "function") {
        handleFontSize();
    } else {
        d.addEventListener("WeixinJSBridgeReady", handleFontSize, false);
    }

    function handleFontSize() {
        // 设置网页字体为默认大小
        WeixinJSBridge.invoke("setFontSizeCallback", { fontSize: 0 });
        // 重写设置网页字体大小的事件
        WeixinJSBridge.on("menu:setfont", function () {
            WeixinJSBridge.invoke("setFontSizeCallback", { fontSize: 0 });
        });
    }
})(window, document);

// 压缩变量混淆版本
!function(k,f,e){function h(){var b=d.getBoundingClientRect().width;b=b>a.maxvw?a.maxvw:b<a.minvw?a.minvw:b;var l=a.rootValue*b/a.ui;d.style.fontSize=l+"px";k.__rem__={fontSize:l,remvw:b,ui:a.ui,base:a.base}}function m(){WeixinJSBridge.invoke("setFontSizeCallback",{fontSize:0});WeixinJSBridge.on("menu:setfont",function(){WeixinJSBridge.invoke("setFontSizeCallback",{fontSize:0})})}var g,d=f.documentElement,c=k.devicePixelRatio||1,a=Object.assign({ui:750,base:375,rootValue:75,minvw:320},e||{});a.maxvw||
(a.maxvw=a.ui);d.setAttribute("data-dpr",c);window.dpr=c;h();2<=c&&(e=f.createElement("body"),c=f.createElement("div"),c.style.border=".5px solid transparent",e.appendChild(c),d.appendChild(e),1===c.offsetHeight&&d.classList.add("hairlines"),d.removeChild(e));window.addEventListener("resize",function(b){clearTimeout(g);g=setTimeout(h,200)},!1);window.addEventListener("pageshow",function(b){b.persisted&&(clearTimeout(g),g=setTimeout(h,200))},!1);"object"==typeof WeixinJSBridge&&"function"==typeof WeixinJSBridge.invoke?
m():f.addEventListener("WeixinJSBridgeReady",m,!1)}(window,document);

2、options 配置参数

参数说明类型默认值
uiUI 设计尺寸number750
baseUI 设计基于真实设备尺寸(例如:iphone6 375px)number375
rootValue请保持与 postcss-pxtorem 中 rootValue 一致(推荐 75、100)number75
minvw适配最小尺寸number320
maxvw适配最大尺寸number(ui 尺寸)

3、初始化(防止闪屏)优化

#app{
	max-width: 750px; // 这里基于UI设计的尺寸
	font-size:24px; // 这里基于UI设计的12px
   	margin: 0 auto;
}