优雅地进行移动端开发

Posted beidan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了优雅地进行移动端开发相关的知识,希望对你有一定的参考价值。

对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范往往会遵循以下两点:

1)选取一款手机的屏幕宽高作为基准(比如 iphone6的375×667)。

2)对于高清屏幕,为了达到高清效果,视觉稿的画布大小会是基准的2倍(对iphone6而言:原先的375×667,就会变成750×1334)。

 

问题1:对于dpr=2的手机,为什么画布大小×2,就可以解决高清问题?

首先,我们要先了解一下 dpr 是什么?

  • 设备像素比(简称dpr)定义了物理像素和设备独立像素的对应关系,它的值可以按如下的公式的得到:
设备像素比 = 物理像素 / 设备独立像素    // 在某一方向上,x方向或者y方向
  • 个物理像素是显示器(手机屏幕)上最小的物理显示单元,在操作系统的调度下,每一个设备像素都有自己的颜色值和亮度值。
  • 设备独立像素,这个点代表一个可以由程序使用的虚拟像素(比如: css像素),然后由相关系统转换为物理像素。  

 总而言之,就是不同的设备(不同的系统),他们有不同的dpr,这些设备在拿到前端写好的页面(即css像素布局)之后,会根据dpr占用不同数量的物理像素。但是,它们最终显示(肉眼识别)的大小是一样的

 盗用一张图:

那这和一开始的问题:对于dpr=2的手机,为什么画布大小×2,就可以解决高清问题? 有什么关系? 再盗用一张图~

这样子就非常清晰了,对于dpr=2的高清(retina)屏幕而言,1个位图像素对应于4个物理像素,由于单个位图像素不可以再进一步分割,所以只能就近取色,从而导致图片模糊(注意上述的几个颜色值)。

因为这样,我们干脆就使用2倍大的图片,比如:200*300的图片,在高清屏上,就使用400*600的图片,但是显示的大小仍然设置为200*300,这样子的话,一个物理像素仍然是显示一个位图像素,完美。

 

 

问题2:类似于下面的布局,在使用最少标签的情况下,如何适配所有移动端屏幕?并且保存一定的宽高比,不失真。

1. 使用百分比 % 进行布局

假如你使用%对该块进行布局,很快,你就会觉得非常的‘苦逼’,由于每一块有margin值,而margin的百分比你很难去计算得到,并且,你可能需要用到各种不同的媒体查询 

@media(max-width:320px){
    div{margin-right: 1%;}
}

每一个屏幕你都可能需要微调,并且,当以后需要修改样式的时候,你又需要每个@media都重新走一遍,想想就后怕

 

2.使用 rem 布局

正所谓,原理大家都懂,rem是根据根元素html的font-size的大小,直接看例子吧~

1 html{font-size: 16px;}
2 body{
3      font-size: 0.5rem;  /*16px * 0.5 = 8px;*/
4 }

基于rem的原理,我们要做的就是:  针对不同手机屏幕尺寸和dpr动态的改变根节点html的font-size大小(基准值)。

回到题目上,那怎么使用rem去实现该布局?并且,在设置rem的过程都非常愉快,不需要经过各种恼人的计算?

根据当前viewport的尺寸来改变html的字体大小,一般分为媒体查询和js动态计算两种。

前者必须针对市面上较为主流的分辨率作媒体查询的区间分界点,缺点是只有设置为分界点的尺寸完美缩放,分界点之间的尺寸会出现断层。

js根据屏幕尺寸去动态计算则能令所有尺寸完美缩放,缺点则是要在页面头部插入一小段js代码。

根据这2个的优缺点,在日常开发中,h5运营页面经常使用js动态计算的方法,而平常的页面(购物,网页)则使用媒体查询的方法。

 

一般在开发中,我们会选择一个屏幕作为基准(比如 iphone6 的 375) ,在该屏幕下,font-size基准设置为20px

先上一个非常巧妙,极大地提高了开发效率但是原理却很简单的方法。

$rem_grid: 20 !default;  //使用 rem(10)即在375屏幕中代表10px
@function rem($val){
    $rem : $val / $rem_grid;   //由于rem是先乘以font-size得出px,所以这里先把rem()传进来的数除以20,最后乘以html的20,其实就是参数的本来值
    @if $rem == 0 {
        @return #{$rem} ;
    }@else{
        @return $rem / ($rem * 0 + 1) * 1rem; // 带不带px单位都支持
    }
}

好了,方便计算的做了,接下来是媒体查询,覆盖常见机型?

原理:根据设备的宽度(与基准设备宽度375的比值)进行缩放。废话不多说,直接上代码

@mixin query( $limit ) {
    @media screen and ( min-width: $limit) {  //媒体查询
        & {
            @content;
        }
    }
}
@mixin _mod_cross( $width, 375 ) {
    @include query( $width * 1px ) {
        font-size:  $width / 375 * 20 * 1px;  //这里是关键
    }
}
@include _mod_cross(320, 375);   //iPhone5

按照上面实现之后,当然,你要@include _mod_cross 常见的机型,这样之后,你就终于终于可以,只在iphone6下,愉快地用rem()进行布局了,无须每一个屏幕都去做适配,也无须每一次都多一步计算,大大提高开发效率。

 

写完媒体查询的方法,再上一份用js动态计算的代码:

原理是一样的,只是使用 document.documentElement.clientWidth 获取更加精确的设备宽度,再对html的font-size进行设置。

<script type="text/javascript">
    !function(){
      var maxWidth=750;
      document.write(\'<style id="o2HtmlFontSize"></style>\');
      var o2_resize=function(){
          var cw,ch;
          if(document&&document.documentElement){
              cw=document.documentElement.clientWidth,ch=document.documentElement.clientHeight;
          }
          if(!cw||!ch){
              if(window.localStorage["o2-cw"]&&window.localStorage["o2-ch"]){
                  cw=parseInt(window.localStorage["o2-cw"]),ch=parseInt(window.localStorage["o2-ch"]);
              }else{
                  chk_cw();//定时检查
                  return ;//出错了
              }
          }
          var zoom=maxWidth&&maxWidth<cw?maxWidth/375:cw/375,zoomY=ch/603;//由ip6 weChat
          window.localStorage["o2-cw"]=cw,window.localStorage["o2-ch"]=ch;
          //zoom=Math.min(zoom,zoomY);//保证ip6 wechat的显示比率
          window.zoom=window.o2Zoom=zoom;
          document.getElementById("o2HtmlFontSize").innerHTML=\'html{font-size:\'+(zoom*20)+\'px;}.o2-zoom,.zoom{zoom:\'+(zoom/2)+\';}.o2-scale{-webkit-transform: scale(\'+zoom/2+\'); transform: scale(\'+zoom/2+\');} .sq_sns_pic_item,.sq_sns_picmod_erea_img{-webkit-transform-origin: 0 0;transform-origin: 0 0;-webkit-transform: scale(\'+zoom/2+\');transform: scale(\'+zoom/2+\');}\';
      },
      siv,
      chk_cw=function(){
          if(siv)return ;//已经存在
          siv=setInterval(function(){
              //定时检查
              document&&document.documentElement&&document.documentElement.clientWidth&&document.documentElement.clientHeight&&(o2_resize(),clearInterval(siv),siv=undefined);
          },100);
      };
      o2_resize();//立即初始化
      window.addEventListener("resize",o2_resize);
  }();
  </script>

 

rem的应用场景:

由于 rem 布局是相对于视口宽度,因此任何需要根据屏幕大小进行变化的元素(width、height、position 等)都可以用 rem 单位。

但 rem 也有它的缺点——不精细,其实这涉及到了浏览器渲染引擎的处理。因此,对于需要精细处理的地方(如通过 CSS 实现的 icon),可以用 px 等绝对单位,然后再通过 transform: scale() 方法等比缩放。

 

以上是关于优雅地进行移动端开发的主要内容,如果未能解决你的问题,请参考以下文章

前端如何优雅的实现跨终端开发(PC端+移动端)

如何高效优雅地管理接口文档

阿里巴巴最新开源项目 - [HandyJSON] 在Swift中优雅地处理JSON

SpringBoot:如何优雅地进行响应数据封装异常处理?

SpringBoot:如何优雅地进行响应数据封装异常处理?

SpringBoot:如何优雅地进行响应数据封装异常处理?