• h5 移动端适配方案思考


    基础概念

    CSS像素(CSS pixels)

    这个是浏览器使用的抽象单位,用来精确度量网页上的内容。平时经常写的100px;height:100px;都是与设备无关的。

    设备独立像素(device independent pixels),也可以称为设备无关的逻辑像素

    meta里面设置width=device-width,这个device-width就是设备独立像素

    在chrome里 看到的ip6为375667,ip4为320480等等都是设备独立像素,它们在数值上与css数值是相等的

    设备像素(device pixels ),也可以称为物理像素

    是显示屏的最小物理单位,每一像素都包含自己的颜色、亮度。像素是没有大小的、是一个抽象概念、是一个相对单位。 关于像素有一个常见的错误理解:认为像素是一个宽高相等的小方块,并且的像素都是“那么大”,但是不知道这个宽高的具体数字。

    分辨率

    泛指量测或显示系统对细节的分辨能力。以ip6手机屏幕为例,分辨率为750×1334,这是指屏幕纵向能显示1920个像素,横向能显示1080个像素

    设备像素比,也成dpr

    设备像素比(简称dpr)定义了物理像素和设备独立像素的对应关系,它的值可以按如下的公式的得到:
    设备像素比 = 物理像素 / 设备独立像素 // 在某一方向上,x方向或者y方向

    适配方案1-固定viewport

    好处:为了宽屏显示更多内容

    日常的 h5 项目使用 viewport 的 initail-scale 为 1,宽度设置配合百分比布局,1px 问题使用 transform 方案会最方便。由于每种设备的设备独立像素不同,最终效果也不同,最后的视觉效果如下:

    问题:如果设计稿中给的是某边框线是 1px,那么按照上述规则,就得设置这个边框为 0.5px,但是部分机型不会支持小数点的 px 尺寸。

    为了得到极细致的真实 1px 单位的边框,衍生出了很多的解决办法,使用的比较多的有两种解决方案。其一为 transform 缩放,其二为动态 viewport。

    transfrom 方案,可以搭配伪元素来使用,如果只是为了得到底边的话,那么设置为高度 1px,然后缩放 y 轴为 0.5。

    .scale {
        position: relative;
    }
    .scale:after {
        content: "";
        position: absolute;
        bottom: 0px;
        left: 0px;
        right: 0px;
        border-bottom: 1px solid #ddd;
        -webkit-transform: scaleY(.5);
                transform: scaleY(.5);
        -webkit-transform-origin :0 0;
                transform-origin :0 0; 
    }
    

    如果需要设置四边的话,则这么设置

    .scale:after{
        content: "";
        pointer-events: none; /* 防止点击触发 */
        box-sizing: border-box;
        position: absolute;
         200%;
        height: 200%;
        left: 0;
        top: 0;
        border-radius: 8px;
        border:1px solid #999;
        -webkit-transform: scale(.5);
                transform: scale(.5);
        -webkit-transform-origin: 0 0;
                transform-origin: 0 0;
    }
    

    适配方案2-动态 viewport 和 REM 适配

    如果是电商的活动页这种对视觉效果比较严谨的,则使用rem和动态viewport方案,最终的视觉效果如下:

    源码如下面,基础思想就是设置根节点元素上得font-size,使之为十六分之一屏幕宽度(类似栅格系统,淘宝为1/10分屏宽,贝贝1/16屏宽)。在设置viewport为1/drp的值就可以了。

    ;(function(win) {
        var h;
        var dpr = win.navigator.appVersion.match(/iphone/gi)?win.devicePixelRatio:1;
        var scale = 1 / dpr;
        var docEl = document.documentElement;
        var metaEl = document.createElement('meta');
        function setUnitA(){
            win.rem = docEl.getBoundingClientRect().width / 16;
            docEl.style.fontSize = win.rem + 'px';
        }
        win.dpr = dpr;
        win.addEventListener('resize', function() {
            clearTimeout(h);
            h = setTimeout(setUnitA, 300);
        }, false);
        win.addEventListener('pageshow', function(e) {
            if (e.persisted) {
                clearTimeout(h);
                h = setTimeout(setUnitA, 300);
            }
        }, false);
        docEl.setAttribute('data-dpr', dpr);
        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 = document.createElement('div');
            wrap.appendChild(metaEl);
            document.write(wrap.innerHTML);
        }
        setUnitA();
    })(window);
    

    iPhone6计算出的根节点元素的font-size为__750px/16=46.876px__,那么跟着设计稿的尺寸,css单位应该这么写:css写的尺寸(单位为rem) = 设计稿里的元素尺寸 / 46.875。这种方案,页面上使用了rem单位的元素在不同倍率手机下css尺寸都不同,例如在iphone5里,css尺寸就是__设计稿元素尺寸 / 46.875 * 40

    然而事情还没有完,如果设计师希望能让大屏的情况显示更多的字,而非把字给这样放大了,那么字体则不能使用rem为单位。看下面的一段代码

    .px2px(@name, @px){
        @{name}: round(@px / 2) * 1px;
        [data-dpr="2"] & {
            @{name}: @px * 1px;
        }
        // for mx3
        [data-dpr="2.5"] & {
            @{name}: round(@px * 2.5 / 2) * 1px;
        }
        // for 小米note
        [data-dpr="2.75"] & {
            @{name}: round(@px * 2.75 / 2) * 1px;
        }
        [data-dpr="3"] & {
            @{name}: round(@px / 2 * 3) * 1px
        }
        // for 三星note4
        [data-dpr="4"] & {
            @{name}: @px * 2px;
        }
    }
    .fontSize(@px) {
        .px2px(font-size, @px);
    }
    

    用法为.fontSize(设计稿里此元素的字体大小) ;,这样就能得到不同倍率下正确的字体大小,不过此法仍然有一个问题,需要穷举出所有的dpr情况,android机子碎片化非常严重,所以总会有一些奇奇怪怪的机型效果不如意。

  • 相关阅读:
    设计模式之模式方法模式
    Extjs 分页多选的实现
    设计模式之策略模式
    oracle 12c 报错 ora-03137 来自客户机的格式错误的TTC包被拒绝
    设计模式之状态模式
    设计模式之装饰者模式
    设计模式之代理模式
    设计模式之单例模式
    从reduce函数说起...
    Django View(视图系统)
  • 原文地址:https://www.cnblogs.com/everlose/p/12496710.html
Copyright © 2020-2023  润新知