zoukankan      html  css  js  c++  java
  • 移动端适配之懒适配

    关于移动端的适配方案,现在其实已经有很多了,什么百分比、font-size+rem、视窗单位(vw、vh)等等,在介绍懒适配之前,先说说我常用的百分比吧。

    百分比布局

      元素的size:页面上的元素的width都使用百分比来实现,比如一行三列,每列就是33.33%,高度可以基于padding-bottom来实现,也可以让内部元素来支撑,这个主要看需求。

      字体大小:这个一般使用px,根据设计图来进行修改,最小12px

      整体页面:设置一个max-width,然后居中显示

      上面差不多就是百分比布局的一些要点,这其中有关size的都需要根据设计图来缩放,计算量还是挺大的,主要是太麻烦。。

    灵感来源

      懒适配的灵感来源是看了淘宝的适配方案,使用viewport来对页面进行缩放,但淘宝的适配不仅仅依赖于此,在这里就不展开了。

    viewport

      <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no,target-densitydpi=device-dpi" />

      解释一下上面这个viewport的作用吧,width=device-width,视窗的width为设备的width。initial-scale=1,初始化的缩放为1(相当于什么都不干)。user-scalable=no,禁止用户手动去缩放(在某些安卓上没有作业)。target-densitydpi=device-dpi,去兼容安卓低版本不支持缩放的问题。

    思路

      使用viewport来进行缩放,缩放的计算公式,设备的可视宽度/设计图的宽度,还有一些兼容和web的处理移动端需要使用meta来缩放,web端需要使用zoom来缩放

      移动端使用meta来进行缩放,因为考虑到需要适配web端,所以必须使用zoom来兼容

      页面所有元素都需要按照设计图来固定size,因为缩放也是安装设计图来进行缩放的

      在开发的过程中遇到android4.4以下和魅族的某些手机使用meta缩放有一些问题,所以这些情况也使用zoom配合target-densitydpi=device-dpi来进行缩放

      对ios设备在手机触发orientationchange事件,screen获取差异进行处理。

      在orientationchange的回调里增加一个定时器,解决某些低端安卓机获取可视区信息延迟的问题

    代码

    不解释了,直接上代码和注释吧

    /*这种设计模式下,移动端需要使用meta来缩放,web端需要使用zoom来缩放
                      页面所有元素都必须按照设计图的尺寸来固定
                  web端的缩放比例,预计的显示宽度/设计图的宽度
                  android 4.4以下对viewport缩放支持不太好,使用zoom配合target-densitydpi=device-dpi来缩放
                      魅族手机使用viewport缩放有点问题,需要使用上面的方法处理
                      
                      手机旋转时,android系浏览器和safari获取视窗的不同
                      
                      假如android和safari的size都是320*640
                      
                      在竖屏模式下   window.screen.width  window.screen.height
                      android        320                  640
                      safari         320                  640
                      
                      在横屏模式下   window.screen.width  window.screen.height
                      android        640                  320
                      safari         320                  640
                      在orientationchange的回调里增加一个定时器,解决某些低端安卓机获取可视区信息延迟的问题
                 **/
    function scale(deWidth,webWidth){//deWidth设计图的宽度,webWidth兼容web页面的宽度,项目在web需要显示的宽度(不能超过deWidth)
        var changeTimer = null,sWidth = window.screen.width;
        if(/iPhone|iPad|iPod/.test(navigator.userAgent)&&typeof window.orientation!=="undefined"&&window.orientation !== 0){
            sWidth = window.screen.height;
        }
        if(navigator.userAgent.indexOf("Mobile")!==-1){
            window.onorientationchange = function(){
                changeTimer&&clearTimeout(changeTimer);
                changeTimer = setTimeout(function(){
                    if(/iPhone|iPad|iPod/.test(navigator.userAgent)&&typeof window.orientation!=="undefined"&&window.orientation !== 0){
                        sWidth = window.screen.height;
                    }else{
                        sWidth = window.screen.width
                    }
                    if(sWidth/deWidth<=1){
                        if (navigator.userAgent.match(/Android (d+.d+)/)){
                            if(parseFloat(navigator.userAgent.match(/Android (d+.d+)/)[1])<4.4||navigator.userAgent.indexOf("MZ-")!==-1){
                                
                                document.documentElement.style.zoom = sWidth/deWidth;
                                return false;
                            }
                        }
                        var meta = document.createElement("meta");
                        meta.setAttribute("name","viewport");
                        meta.setAttribute("content","width=device-width,initial-scale="+(sWidth/deWidth).toFixed(2)+",user-scalable=no,target-densitydpi=device-dpi");
                        
                        document.querySelector("[name=viewport]").remove();
                        document.head.appendChild(meta);
                    }
                },500)
            }
            if(sWidth/deWidth<=1){
                if (navigator.userAgent.match(/Android (d+.d+)/)){
                    
                    if(parseFloat(navigator.userAgent.match(/Android (d+.d+)/)[1])<4.4||navigator.userAgent.indexOf("MZ-")!==-1){
                        document.documentElement.style.zoom = sWidth/deWidth;
                        return false;
                    }
                }
                
                var meta = document.createElement("meta");
                    meta.setAttribute("name","viewport");
                    meta.setAttribute("content","width=device-width,initial-scale="+(sWidth/deWidth).toFixed(2)+",user-scalable=no,target-densitydpi=device-dpi");
                    document.querySelector("[name=viewport]").remove();
                    document.head.appendChild(meta);
            }
        }else{
            document.documentElement.style.zoom = webWidth/deWidth;
        }
    }

    可以在这里看看效果 demo

    2017-07-03 update

    解决window.screen在某些情况下,获取到的并不是可视区的问题,使用document.documentElement.clientWidth代替

    在resize的时候还原zoom或者meta 重新去获取正确的视窗信息(因为缩放的原因,拿到的size是被放大了,之所以不记录缩放系数,因为有可能导致精度问题)

    解决firefox不支持zoom,使用scale兼容

    缩放规则更改
    在安卓设备(4.4以上)上统一使用zoom来缩放(meta,target-densitydpi=device-dpi在某些内核下会自带缩放,即使没有设置initial-scale)

    安卓设备(4.4以下)使用zoom + target-densitydpi=device-dpi

    非安卓的使用<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no" />来缩放

    var Scale = {
        init:function(deWidth,webWidth){
            var that = this,changeTimer = null;
            that.sWidth = document.documentElement.clientWidth;
            that.deWidth = deWidth;
            that.webWidth = webWidth;
            if(navigator.userAgent.match(/Android (d+.d+)/)&&(parseFloat(navigator.userAgent.match(/Android (d+.d+)/)[1])<4.4)){
                            var meta = document.createElement("meta");
                                meta.setAttribute("name","viewport");
                                meta.setAttribute("content","width=device-width,initial-scale=1,user-scalable=no,target-densitydpi=device-dpi");
                                
                                document.querySelector("[name=viewport]").remove();
                                document.head.appendChild(meta);
            }
            if(navigator.userAgent.indexOf("Mobile")!==-1){
                window.onorientationchange = function(){
                    that.resetScale();
                    changeTimer&&clearTimeout(changeTimer);
                    changeTimer = setTimeout(function(){
                        that.sWidth = document.documentElement.clientWidth;
                        taht.setScale();
                    },500)
                }
                that.setScale();
            }else{
                if(navigator.userAgent.indexOf("Firefox")!==-1){
                    document.documentElement.style.transform = "scale("+that.webWidth/that.deWidth+")";
                }else{
                    document.documentElement.style.zoom = that.webWidth/that.deWidth;
                }
            }
        },
        setScale:function(){
            var that = this;
            if(that.sWidth/that.deWidth<=1){
                if(navigator.userAgent.match(/Android (d+.d+)/)){
                    document.documentElement.style.zoom = that.sWidth/that.deWidth;
                }else{
                    var meta = document.createElement("meta");
                    meta.setAttribute("name","viewport");
                    meta.setAttribute("content","width=device-width,initial-scale="+(that.sWidth/that.deWidth)+",user-scalable=no");
                    document.querySelector("[name=viewport]").remove();
                    document.head.appendChild(meta);
                }
                
                
            }
        },
        resetScale:function(){
            document.documentElement.style.zoom = 1;
            var meta = document.createElement("meta");
            meta.setAttribute("name","viewport");
            meta.setAttribute("content","width=device-width,initial-scale=1,user-scalable=no");
            document.querySelector("[name=viewport]").remove();
            document.head.appendChild(meta);
                        
        }
    }

    结语

    上面只是粗略的代码,可优化的地方还很多,最主要是这种懒适配的思想,当然,因为这种方法使用的较少,应该还存在很多的问题,欢迎指出。

  • 相关阅读:
    2.安卓体系结构
    1.Android的历史与安装
    Mysql免安装配置
    安装gulp
    搭建vue开发环境的步骤
    运行一个从GitHub上下载的vue项目的具体步骤
    网站源码,大量HTML5模板,视频源码,黑客技术资源
    bootstrap文件树
    jQuery unbind 某个function
    响应式设计的思考:媒体查询(media query)
  • 原文地址:https://www.cnblogs.com/jesse007/p/7054209.html
Copyright © 2011-2022 走看看