移動端設計方案--如何更好的設計移動端高清方案

一、前言

有時候需要前端做到移動端高清顯示,1、面對開發移動端H5頁面,2、面對不同分辨率的手機,3、面對不同屏幕尺寸的手機。

 

二、視覺稿

前端開發正常是,視覺的小哥哥給我們psd或者導出的skech文件,這個就是視覺稿,然後前端開始寫結構,寫元素,調整,優化等等。

對於移動端開發而言,達到頁面高清的效果,視覺稿的規範往往會遵循這兩點:

(1)選取一款手機的屏幕寬高作爲基準(以前是iphone4的320*480,現在更多的是iphone6的375*667)。

(2)對於retina屏幕(可以將更多的像素點壓縮至一塊屏幕裏,從而達到更高的分辨率並提高屏幕顯示的細膩程度)(如:dpr=2),爲了達到高清效果,視覺稿的畫布大小會是基準的2倍,也就是說像素點個數是原來的4倍(比如iphone6的,原先的375*667,就會變成750*1334)。

肯定有疑問:(1)爲啥dpr=2的手機,爲什麼畫布大小*2,就可以解決高清問題?(2)對於2倍大小的視覺稿,具體的css是如何還原每一個區塊的真實寬高(佈局問題)?

 

三、基礎概念

1、物理像素:一個物理像素是顯示器(手機屏幕)上最小的物理顯示單元,在操作系統的調度下,每一個設備像素都有自己的顏色值和亮度值。

2、設備獨立像素:設備獨立像素也叫與密度無關像素,可以認爲是計算機座標系統中得到一個點,這個點代表一個可以由程序使用的虛擬像素(比如:css像素),然後由相關係統轉換爲物理像素。

所以,物理像素和設備獨立像素之間存在一定的對應關係,這就是要說的設備像素比

3、設備像素比:設備像素比(簡稱爲dpr)定義了物理像素和設備獨立像素的對應關係,它的值可以根據公式計算得出:

設備像素比 = 物理像素 / 設備獨立像素 // 在某一方向上,x方向或者y方向

在javascript中,可以通過window.devicePixelRatio方法獲取當前設備的dpr。

在css中,通過-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和-webkit-max-device-pixel-ratio進行媒體查詢,對於不同的dpr的設備,做一些樣式適配(主要是針對webkit內核的瀏覽器和webview)。

 

4、舉個例子

以iphone6爲例:

(1)設備寬高爲375*667,可以理解成設備的獨立像素(css像素);

(2)dpr爲2,根據上面計算公式,物理像素應該就是750*1334。

用一張圖來表現,就是這樣(原諒我的盜圖):

在不同的屏幕上(普通屏幕 vs retina屏幕),css像素所呈現的大小是一致的,不同的是1個css像素所對應的物理像素個數是不一致的。

在普通屏幕下,1個css像素 對應 1個物理像素(1:1)。 在retina 屏幕下,1個css像素對應 4個物理像素(1:4)。

 

5、位圖像素

一個位圖像素是柵格圖像(如:png,jpg,gif等)最小的數據單元。每一個位圖像素都包含了一些自身的顯示信息(如:顯示位置,顏色值,透明度等)。

理論上:一個位圖像素對應於1個物理像素,圖片才能得到完美清晰的展示。。

普通屏幕沒有問題的,但是在retina屏幕下會出現位圖像素點不夠,從而導致圖片模糊的情況。

看一張圖:

如圖所示:對於dpr=2的retina屏幕而言,1個位圖像素對於4個物理像素,由於單個位圖像像素不可以在分隔,只能就近取色,從而導致圖片模糊。

所以對於圖片高清的問題,比較好的方案是兩倍圖片(長寬增大到2倍)

如:200×300(css pixel)img標籤,就需要提供400×600的圖片。

如此下來,位像素點個數就是原來的4倍,在retina屏幕下,位圖像素點個數就可以跟物理像素點個數形成1:1的比例,圖片自然就清晰了,解決了第一個疑問。

 

如果出現,普通屏幕下,也用了兩倍圖片,會怎麼樣?

很明顯,在普通屏幕下,200×300(css pixel)img標籤,所對應的物理像素個數就是200×300個,而兩倍圖片的位圖像素個數則是200×300*4,所以就出現1個物理像素點對應4個位圖像素點,它的取色也只能通過一定的算法(顯示結果就是一張只有原圖像素總數四分之一,我們稱這個過程叫做downsampling(降採樣,降低數據採樣率或分辨率的過程)).肉眼看上去雖然圖片不會模糊,但是會覺得圖片缺少一些銳利度,或者是有點色差(但還是可以接受的)。

 

四、總結

移動端H5開發,在不同的分辨率,不同屏幕的手機下會遇到幾個經典問題

1、retina下,圖片高清的問題

上面已經講到了解決方案:圖片的長寬的兩倍,然後圖片容器縮小50%。

比如:

1、img 標籤

width: 200px;
height: 300px;

2、背景圖片

width: 200px;
height: 300px;
background-image: url(image@2x.jpg);
background-size: 200px 300px; // 或者: background-size: contain;

這樣的缺點就是,普通屏幕下:

1、同樣下載長度都2倍的圖片,造成了資源浪費。

2、圖片由於downSampling,會失去一些銳利度(或者色差)。

所以最好的解決辦法:不同的dpr下,加載不同的尺寸的圖片。

不管是通過css媒體查詢,還是通過js條件判斷都是可以的。所以需要準備兩套圖片。

 

2、retina下,border:1px的問題

1px是設計師用他的像素眼,最關心的問題。

還是通過一張圖來解釋(原諒我再次盜圖):

 

上圖中,對於一條1px寬的直線,它們在屏幕上的物理尺寸(灰色區域)的確是相同的,不同的其實是屏幕上最小的物理顯示單元,即物理像素,所以對於一條直線,iphone5它能顯示的最小寬度其實是圖中的紅線圈出來的灰色區域,用css來表示,理論上說是0.5px

所以,設計師想要的retina下border: 1px;,其實就是1物理像素寬,對於css而言,可以認爲是border: 0.5px;,這是retina下(dpr=2)下能顯示的最小單位。

然而,無奈並不是所有手機瀏覽器都能識別border: 0.5px;,ios7以下,android等其他系統裏,0.5px會被當成爲0px處理,那麼如何實現這0.5px呢?

最簡單的一個做法就是這樣(元素scale):

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

我們照常寫border-bottom: 1px solid #ddd;,然後通過transform: scaleY(.5)縮小0.5倍來達到0.5px的效果,但是這樣hack實在是不夠通用(如:圓角等),寫起來也麻煩。

或者可以使用js來判斷當前瀏覽器是否支持border的0.5px,如果支持就會在HTML上添加一個class名hairlines

if (window.devicePixelRatio && devicePixelRatio >= 2) {
  var testElem = document.createElement('div');
  testElem.style.border = '.5px solid transparent';
  document.body.appendChild(testElem);
  if (testElem.offsetHeight == 1)
  {
    document.querySelector('html').classList.add('hairlines');
  }
  document.body.removeChild(testElem);
}

css

div {
  border: 1px solid #bbb;
}
 
.hairlines div {
  border-width: 0.5px;
}

 

五、參考

1、http://www.smashingmagazine.com/2012/08/20/towards-retina-web/

2、http://www.paintcodeapp.com/news/iphone-6-screens-demystified

3、http://iconmoon.com/blog2/iphone-6-plus-screen-size/

4、http://dieulot.net/css-retina-hairline

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章