移动端自适应布局 rem方案

1、viewport.js

(function(window, document) {
    // 给hotcss开辟个命名空间,别问我为什么,我要给你准备你会用到的方法,免得用到的时候还要自己写。
    const hotcss = {}
;(function() {
        // 根据devicePixelRatio自定计算scale
        // 可以有效解决移动端1px这个世纪难题。
        let viewportEl = document.querySelector("meta[name="viewport"]"),
            hotcssEl = document.querySelector("meta[name="hotcss"]"),
            dpr = window.devicePixelRatio || 1,
            maxWidth = 540,
            designWidth = 0

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

        // 允许通过自定义name为hotcss的meta头,通过initial-dpr来强制定义页面缩放
        if (hotcssEl) {
            const hotcssCon = hotcssEl.getAttribute("content")
;if (hotcssCon) {
                const initialDprMatch = hotcssCon.match(/initial-dpr=([d.]+)/)
                if (initialDprMatch) {
                    dpr = parseFloat(initialDprMatch[1])
                }
                const maxWidthMatch = hotcssCon.match(/max-width=([d.]+)/)
                if (maxWidthMatch) {
                    maxWidth = parseFloat(maxWidthMatch[1])
                }
                const 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 // 保证px2rem 和 rem2px 不传第二个参数时, 获取hotcss.designWidth是undefined导致的NaN

        let 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) * 320 / designWidth / 20
    }

    hotcss.rem2px = function(rem, designWidth) {
        // 新增一个rem2px的方法。用法和px2rem一致。
        if (!designWidth) {
            designWidth = parseInt(hotcss.designWidth, 10)
        }
        // rem可能为小数,这里不再做处理了
        return rem * 20 * designWidth / 320
    }

    hotcss.mresize = function() {
        // 对,这个就是核心方法了,给HTML设置font-size。
        let 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 * 20 / 320}px`
        ;hotcss.callback && hotcss.callback()
    }

    hotcss.mresize()
    // 直接调用一次

    window.addEventListener("resize", () => {
        clearTimeout(hotcss.tid)
        ;hotcss.tid = setTimeout(hotcss.mresize, 33)
    }, false)
    // 绑定resize的时候调用

    window.addEventListener("load", hotcss.mresize, false)
    // 防止不明原因的bug。load之后再调用一次。


    setTimeout(() => {
        hotcss.mresize()
        // 防止某些机型怪异现象,异步再调用一次
    }, 333)

    window.hotcss = hotcss
    // 命名空间暴露给你,控制权交给你,想怎么调怎么调。
})(window, document)

2、使用

页面中直接引用viewport.js即可。

原文地址:https://www.cnblogs.com/mengfangui/p/10234267.html