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

1、前言javascript

有時候須要前端作到移動端高清顯示,一、面對開發移動端H5頁面,二、面對不一樣分辨率的手機,三、面對不一樣屏幕尺寸的手機。css

 

2、視覺稿html

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

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

(1)選取一款手機的屏幕寬高做爲基準(之前是iphone4的320*480,如今更多的是iphone6的375*667)。android

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

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

 

3、基礎概念算法

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

二、設備獨立像素:設備獨立像素也叫與密度無關像素,能夠認爲是計算機座標系統中獲得一個點,這個點表明一個能夠由程序使用的虛擬像素(好比:css像素),而後由相關係統轉換爲物理像素。

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

三、設備像素比:設備像素比(簡稱爲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)。

 

四、舉個例子

以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)。

 

五、位圖像素

一個位圖像素是柵格圖像(如: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(降採樣,下降數據採樣率或分辨率的過程)).肉眼看上去雖然圖片不會模糊,可是會以爲圖片缺乏一些銳利度,或者是有點色差(但仍是能夠接受的)。

 

4、總結

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

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

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

好比:

一、img 標籤

width: 200px; height: 300px;

二、背景圖片

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

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

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

二、圖片因爲downSampling,會失去一些銳利度(或者色差)。

因此最好的解決辦法:不一樣的dpr下,加載不一樣的尺寸的圖片。

不論是經過css媒體查詢,仍是經過js條件判斷都是能夠的。因此須要準備兩套圖片。

 

二、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; }

 

5、參考

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

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

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

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

相關文章
相關標籤/搜索