美文网首页
H5 android老人机适配方案

H5 android老人机适配方案

作者: 风之化身呀 | 来源:发表于2018-04-12 12:10 被阅读208次

    前言

    部门移动端布局采用的是rem+font-size的方案,这种方案中font-size的值至关重要。正常情况下页面不会出现布局错乱现象,但是部分android机,通过改变系统默认字号(若改成大号字体)会导致font-size值被放大,相当于乘了一个放大因子scale,从而导致页面布局错乱,本文就是解决这个问题。
    (所谓老人机,这里指手动修改了系统默认字体或缩放设置)

    举例

    数据来源:三星S8手机

    系统缩放设置 系统字体设置 clientWidth font-size(clientWidth/7.5) 布局是否正常
    412 54.93
    412 54.93
    412 54.93
    360 48
    360 48
    360 48
    320 42.67
    320 42.67
    320 42.67

    结论:
    1、系统缩放设置(部分手机能设置该项)可改变clientWidth(取自document.documentElement.clientWidth);
    2、同缩放下,系统默认字体被修改后,虽然font-size值没变,但在渲染时实际上被隐式放大或缩小了,记为缩放因子scale;

    方案

    思路:这个缩放因子scale很重要,它是导致页面布局错乱的罪魁祸首,如果知道这个scale,那么取其倒数,就可以恢复正常。
    先看看rem+font-size的布局套路:

    <!DOCTYPE html>
    <html>
    <head>
        <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
        <title>墨粉club</title>
        <script>
        (function() {
            var maxLimitW = 768,
                remCount = 7.5,
                clientW = document.documentElement.clientWidth||document.body.clientWidth;
            var initFontSize = Math.min(maxLimitW, clientW) / remCount;
            document.documentElement.style.fontSize = initFontSize + 'px';
        })();
        </script>
    </head>
    

    由上表可知,缩放程度为中,默认字体为小时,页面正常显示。现在考虑缩放程度为中,默认字体为中的情形:
    字面上计算的font-size没变(记为F1),但实际上渲染时的font-size是被放大了的,记为(F1=F2*scale),得出scale=F1/F2;
    关键点:scale还可以这么计算,正常情况下,我们认为页面宽度被分为7.5份,但缩放后页面肯定不是7.5份了,假设缩放后页面宽度被分为N份,则scale*N=7.5,得scale=7.5/N;所以有7.5/N=F1/F2,从而有F2=F1*N/7.5;只要计算出N,就能计算出F2。
    下面就是如何计算N:

     document.addEventListener('DOMContentLoaded', function() {
                var remFixDom = document.createElement("div");
                remFixDom.style.cssText = "width:100%;height:1rem;opacity:0;position:absolute;z-index:-9999;";
                document.body.appendChild(remFixDom);
                var render = window.getComputedStyle(remFixDom);
                var N = (render.width.slice(0, -2) / render.height.slice(0, -2)).toFixed(1);
                setTimeout(function() {
                    remFixDom.style.cssText = "height:0";
                }, 1000)
            });
    

    算出F2后,设置为html的font-size=F2即可修复该问题。
    完整代码:

     (function() {
            var maxLimitW = 768,
                remCount = 7.5,
                clientW = document.documentElement.clientWidth,
                hasReadyInit;
            // 兼容三星S8 bug,只有第一次进入时才能取得clientW的值,第二次进该值为0,所以用localStorage存起来
            if (clientW) {
                localStorage.setItem('clientW', clientW);
            } else {
                clientW = localStorage.getItem('clientW');
            }
            var initFontSize = Math.min(maxLimitW, clientW) / remCount;
            document.documentElement.style.fontSize = initFontSize + 'px';
            // 修正系统设置了字号之后,支持动态字体的APP会强制调整网页font-size,导致rem方式的适配乱版问题(比如下面ua)
            //eg. 华为QQ内置浏览器 Android 7.0; EVA-AL00 Build/HUAWEIEVA-AL00; wv) Mobile MQQBrowser/6.2 QQ/7.1.5.3215
            if (clientW >= maxLimitW) return;
            if (hasReadyInit) return; //已经注册过ready修正事件了
            document.addEventListener('DOMContentLoaded', function() {
                var remFixDom = document.createElement("div");
                remFixDom.style.cssText = "width:100%;height:1rem;opacity:0;position:absolute;z-index:-9999;";
                document.body.appendChild(remFixDom);
                var render = window.getComputedStyle(remFixDom);
                var rRate = (render.width.slice(0, -2) / render.height.slice(0, -2)).toFixed(1);
                var finalFontSize = initFontSize * (rRate / remCount);
                if (finalFontSize) {
                    localStorage.setItem('finalFontSize', finalFontSize);
                } else {
                    finalFontSize = localStorage.getItem('finalFontSize');
                }
                if (rRate != remCount) document.documentElement.style.fontSize = finalFontSize + "px";
                hasReadyInit = true;
                setTimeout(function() {
                    remFixDom.style.cssText = "height:0";
                }, 1000)
            });
        })();
    

    相关文章

      网友评论

          本文标题:H5 android老人机适配方案

          本文链接:https://www.haomeiwen.com/subject/ygzzhftx.html