移動端適配


對於移動端開發而言,為了做到頁面高清的效果,視覺稿的規范往往會遵循以下兩點:

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() 方法等比縮放。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM