淺談移動Web開發(上):深入概念

來源:互聯網
上載者:User

標籤:

PPI什麼是PPI

PPI的複雜之處在於如果他所屬的上下文環境不同,意義也會完全不一樣。 當我們在談論顯示裝置的PPI時,它代指的螢幕的像素密度;當我們在談論和圖片相關時,我們談論的是列印時的解析度或者印表機的列印精度。這裡我們主要描述的前一種情況.

PPI全稱為Pixel Per Inch,譯為每英吋像素取值,更確切的說法應該是像素密度,也就是衡量單位物理面積內擁有像素值的情況。

 

如所示,在1英寸單位內面積內擁有的像素越多,密度越大,PPI值就越高。但像素密度的實際意義是什嗎?它表達的是什嗎?或高或低對裝置顯示來說有什麼影響?

一般來說,我們當然希望PPI值越高越好,因為更高的PPI意味著在同一實際尺寸的物理螢幕上能容納更多的像素,能夠展現更多的畫面細節,也就意味著更平滑的畫面。原理如下:

什麼是Pixel

但你有沒有仔細相關Pixel Per Inch中的pixel像素的概念究竟指的是什麼樣的像素?你可能會反問我像素難道還分很多種不成?我可以很確定的告訴你,是的。

裝置像素

無論是早期的CRT顯示器還是如今的LCD顯示器,都是基於點陣的。也就是說通過一些列的小點排列成一個大的矩形,不同的小點通過顯示不同的顏色來顯示成映像。比如就是LCD顯示器上一個6x6個小點排列成的矩陣:

注意每一個像素(pixel,也可以稱之為dot)又是由三個子像素(subpixel)紅綠藍組合而成。當需要顯示圖片資訊時,它的工作原理可以如所示:

中的左側是放大之後我們能看到的像素,而右側就是對應像素在顯示器上的顯示情況了。

注意代表的僅是LCD顯示器的物理像素情況,早期的CRT顯示器的物理像素同樣也是由獨立的點組成。但是不存在subpixel的概念,情況如所示:

上面描述的這些顯示器上的像素我們就稱之為物理像素(physical pixel)或者裝置像素(device pixel)。

CSS像素

作為Web開發人員,我們接觸的更多的是用於控制元素樣式的樣式單位像素。這裡的像素我們稱之為CSS像素。

CSS像素有什麼特別的地方?我們可以借用quirksmode中的這個例子:

假設我們用PC瀏覽器開啟一個頁面,瀏覽器此時的寬度為800px,頁面上同時有一個400px寬的區塊層級元素容器。很明顯此時塊狀容器應該占頁面的一半。

但如果我們把頁面放大(通過“Ctrl鍵”加上“+號鍵”),放大為200%,也就是原來的兩倍。此時塊狀容器則橫向佔滿了整個瀏覽器。

弔詭的是此時我們既沒有調整瀏覽器視窗大小,也沒有改變塊狀元素的css寬度,但是它看上去卻變大了一倍——這是因為我們把CSS像素放大為了原來的兩倍。

CSS像素與螢幕像素1:1同樣大小時:

CSS像素(黑色邊框)開始被展開,此時1個CSS像素大於1個螢幕像素

也就是說預設情況下一個CSS像素應該是等於一個物理像素的寬度的,但是瀏覽器的放大操作讓一個CSS像素等於了兩個裝置像素寬度。在後面你會看到更複雜的情況,在高PPI的裝置上,CSS像素甚至在預設狀態下就相當於多個物理像素的尺寸。

通過上面這個例子我想傳遞一個非常重要的概念,就是CSS像素從來都只是一個相對值。

正確答案

回到PPI上來,現在我們有了兩種像素,裝置像素和CSS像素。那麼PPI中的像素是指哪一種?

請記住,PPI中的pixel指的應該是物理像素

但是在維基百科對PPI的解釋中,pixel被解釋為一種類似於解析度下的像素:

The apparent PPI of a monitor depends upon the screen resolution (that is, the number of pixels) and the size of the screen in use; a monitor in 800×600 mode has a lower PPI than does the same monitor in a 1024×768 or 1280×960 mode.

上面這段話是在說,同一尺寸的顯示器在800x600分辨與1024x768解析度下的像素密度明顯是不同的,明顯後者單位面積內的像素更多,當然後者的像素密度更高。

這裡考慮了另一種情況,即在同一顯示器下因為解析度調整導致顯示器的像素密度不同。這裡的像素雖然是不是在瀏覽器中顯示,但原理也類似於CSS像素,即由多個物理像素組成一個指定解析度下的像素。

但問題是,這樣的比較是沒有任何意義的,我們通常在比較PPI時,一定是在跨裝置比較,為了體現裝置的技術優勢,也一定是拿裝置的最優或者極限情況進行比較,這樣情況下解析度下像素是與物理像素一一匹配的。 不能說一台23寸的2k顯示器和一台23寸的1080p顯示器因為都能調整到1440x960的解析度,那麼他們的PPI就相同了?PPI終究是體現裝置某方面效能的參數。

也就是說,當我們在談論一台裝置的PPI時,它是一個定值,是一個固定的參數。

那麼PPI怎麼計算呢?沒錯,就和你想的一模一樣,用螢幕邊的物理像素除以物理尺寸即可,以Samsung Galaxy S4為例:

由此可見Galaxy S4的螢幕解析度為441PPI。

The Bad and the Ugly

但PPI過高同樣也會帶來問題,相同的圖片素材,在越高的裝置上會顯示的越小。以下是一個像素在不同PPI裝置上的可見情況,隨著PPI的增高可視度越來越小:

那麼可以預見一種很糟糕的情況是,同一尺寸的螢幕下假設PPI提高了一倍,很可能程式介面縮小了4倍(因為在螢幕尺寸不變的情況下物理像素點面積是原來的1/4)。

以Surface Pro 3為例,它的預設解析度是2160x1440,也就是說Surface這台裝置的螢幕物理像素有2160x1440個點,同時預設解析度情況下,一個點物理像素點對應於一個解析度像素。 但因為螢幕只有12寸,像素密度非常高,於是就出現了上面的問題,各個文字和表徵圖被縮的太小了,電腦是完全停用。

解決方案是,Windows預設將所有的文本和素材(實際上就是解析度像素)都放大了1.5倍(在“螢幕解析度”-“放大或縮小文本和其他項”中進行了設定),原來是一個物理像素對應一個解析度下的像素,現在則是1.5個物理像素對應一個解析度下的像素,也就意味著解析度下的像素變大了,實際解析度降低了,已經變成了1440(2160/1.5)x900(1440/1.5)(此時如果你嘗試用window.screen.width/window.screen.height去檢測返回結果也會是1440x900)。這裡留給讀者一個問題,

這樣和直接將PC的解析度調整為1440x900有什麼區別呢?

但把素材和文字放大就真的一勞永逸了嗎?不,甚至還會帶來副作用。放大素材對位元影像來說是非常危險的一件事。假設一款軟體中的素材圖片解析度為32x32,但是為了配合整體介面的展開,它也必須被展開至原來的1.5倍等於為48x48。你一定有在Photoshop中把圖片強制放大為原來幾倍的效果的經驗。 這樣以來,圖片素材就變得模糊了。同時因為Window使用的字型為點陣字型而非向量字型,所以甚至在軟體中的字型也會變得模糊。

簡單一點來說,採用這種技術需要將32x32的圖片強制展開為48x48,多出來的像素如何憑空產生?電腦只有猜測了,通過線性插值演算法。所以圖片便會出現模

糊。

但位元影像可能會被展開的問題並非也是絕對的,假設軟體需要顯示的icon大小為32x32,但是圖片素材大小為64x64,那麼即使Windows的UI介面展開1.5倍,icon大小為48x48,因為原圖片足夠大,圖片仍處於未展開的狀態。那麼也不會模糊。

反過來我們可以得出結論,為了讓在低PPI上和高PPI片顯示的效果一致,圖片素材應該儘可能的高清。

Apple的Retina技術使用的也是上面相同的方案。以15.4寸的Retina版Macbook Pro為例。顯示屏的物理像素點實際上有2880x1880,但其實預設的最優解析度只有1440x900,剛好是物理像素的一半。也就是說作業系統預設使用了4:1的縮放。但這同樣也有可能會出現使用軟體虛化的問題。

我不清楚Mac軟體開發中是如何解決這個問題的,但可以參考iPhone開發中的解決方案,蘋果鼓勵開發人員準備兩份素材,普通和高清素材。並且通過素材檔案名稱尾碼來區分,比如普通素材名稱為apple.png,那麼高清素材名稱就為[email protected]。自然高清素材是普通素材面積的四倍,系統會優先使用高清素材,但自動縮小到普通素材的大小,這樣也就不存在圖片展開的問題了。

PPI之於Web

從上面我們得知,因為高像素密度裝置下的UI會採用一定比例的縮放,所以CSS像素也會面臨同樣的問題:

正如所示,左側普通螢幕中,2x2的CSS像素真的只需要2x2的物理像素。但是右側高清屏中,2x2的CSS像素卻需要4x4的物理像素。

我剛剛有說道解決高清PPI片渲染問題的方法之一就是使用更高清的圖片素材。但問題是需要有多高清?

在Retina顯示屏上,根據上一節描述的原理,當我們需要渲染一張32x32的圖片,我們實際上需要準備64x64的素材。因為蘋果預設把所有素材都進行了兩倍的放大。但如果有一台更高清的裝置,進行了三倍或者四倍或者更高的倍數,我們豈不是需要準備更多尺寸或者體積更大的檔案素材?在Web開發中我們正在面臨這樣的問題。

首先我們要學會如何表達和判斷這樣一種CSS像素和物理像素不平等。

DevicePixelRatio

DevicePixelRatio定義如下:

window.devicePixelRatio = physical pixels / dips

分母dips全稱為device-independent pixels,譯為與裝置無關像素。 更通俗的說應為與物理像素無關的CSS像素。

以iPhone4為例,在垂直狀態下手機的物理像素寬度有640px,但是因為2:1縮放的關係,此時的dip,裝置報告給我們的寬度只是320px。 此時的DevicePixelRatio就為 640 / 320 = 2;

devicePixelRatio說白了就是手機的物理像素與實際使用像素的縮放比。

注意devicePixelRatio並非是一個預設值。在預設情況下CSS像素是由手機預設的縮放決定的。但同時因為瀏覽器頁面也可以被人為的進行縮放。比如iPhon4中預設的解析度寬度為320px。瀏覽網頁時我們完全可以自行放大兩倍為160px。這樣以來window.devicePixelRatio就變味了 640 / 160 = 4。

dppx

與divicePixelRatio幾乎等價的一個概念時dppx:dots per pixel。 表示單個CSS像素佔用的物理像素個數。仔細想想,這與devicePixelRatio其實是一個意思, iPhone4的dppx為2,不就是與devicePixelRatio剛好相等嗎。devicePixelRatio是從宏觀上來說這件事。把整體寬度做運算。dppx是從微觀角度上說這件事,考慮的是單個像素之間的比較。

dpi

請記住,當我們在談論一台顯示裝置的像素密度時,dpi與ppi是等價的。dots per pixel中的dots就是代指物理像素。

但是如果你在mediaquery中使用dpi是就要注意了,Chrome會在控制台中提示你使用dppx而非dpi:

Consider using ‘dppx’ units instead of ‘dpi’, as in CSS ‘dpi’ means dots-per-CSS-inch, not dots-per-physical-inch, so does not correspond to the actual ‘dpi’ of a screen. In media query expression: only screen and (-webkit-min-device-pixel-ratio: 2), not all, not all, only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx)

上面這段話的意思是,在mediaquery中inch表示的CSS定義中的一英寸,而非生活中物理定義的一英寸。

實話實說我並沒有找到關於CSS中一英寸的定義,但是在W3C關於Resolution的定義中,我們可以看到看到它所定義的1dppx是與96dpi具有同樣含義的。那麼2dppx也就是192dpi了咯。這當然脫離了我們傳統上的dpi了,Surface Pro 3的dpi(也就是ppi)能夠達到216ppi,但是在預設未放大介面時的dppx仍然可以是1。

CSS Reference Pixel

個人人為這是一個很雞肋的概念,但也正是因為瞭解的人太少了,還是需要值得一提。

假設我們規定了CSS像素值需要與裝置像素大小相等,但當隨著手持功能距離人的遠近不同,裝置像素密度的不同,都會導致我們看見的裝置上的CSS像素的可見大小發生變化(類似於巨大的月亮因為離地球遙遠在人眼看來也不過像硬幣一樣大小)。為了保證CSS像素在不同裝置和不同距離上觀測到的大小保持一致保持連貫性。W3C定義了一個CSS相對像素(CSS reference pixel)的概念

It is recommended that the reference pixel be the visual angle of one pixel on a device with a pixel density of 96dpi and a distance from the reader of an arm’s length. For a nominal arm’s length of 28 inches, the visual angle is therefore about 0.0213 degrees.

W3C規定,把人眼能夠辨別到的,距離自己一個手臂長度(約28英寸),像素密度為96dpi裝置上的一個物理像素設為參考像素。所以我們可以算出眼睛看到參考像素的視野角度為0.0213度:

有了這一系列參照,通過三角函數關係,我們可以算出同樣一台裝置在不同距離下CSS像素理想的大小。 當遠離觀察者時像素應該增大,當靠近觀察者時像素應該減小:

這麼做的優勢在於無論裝置距離觀察者距離是多少,也無論裝置的像素密度和物理像素大小是多少,觀察者看到的CSS像素是一致的,保證了使用者體驗的一致性:

但問題是如何來實踐這一標準呢?

<meta name="viewport">

我們有了物理像素,CSS像素——那麼問題來了,當你再手機上使用瀏覽器開啟網頁時,網頁應該按照哪一種寬度進行渲染?

首先我們需要瞭解一個概念:viewport,我常見到的中文譯為視口,但個人覺得這個翻譯有一些晦澀。 Viewport是用於限制Html元素——“限制”這兩個字不是那麼好理解。quirksmode上有一篇文章談到這個概念時打了一個非常形象的比方:

假設body標籤內有一個塊狀元素寬度為10%: div {width:10%;},我們知道當我們縮放瀏覽器時這個塊狀元素的寬度也會跟著變化。 這是因為它的寬度占它父元素的10%。那麼它的父元素,也就是body元素的寬度是由誰決定的呢?

我們知道一個塊狀元素預設寬度為它父元素的100%,也就是body元素的寬度與包裹它的html元素寬度相同。那麼問題又變成了html元素的寬度是由誰決定的?

答案是瀏覽器視窗。現在我們可以歸納起來,html元素是被瀏覽器限制並且包裹起來的。html的寬度就是瀏覽器的寬度。

但事實上,html元素寬度是佔據viewport的100%,而在案頭瀏覽器中,viewport與瀏覽器視窗大小剛好相等(注意,這僅僅是在案頭瀏覽器上)。

OK,在於是我們得到了一個結論,html寬度是由viewport決定的,但是 在案頭瀏覽器中,viewport大小與瀏覽器視窗大小相等。

但這一套規則在手機則是無法被執行的。大部分手機的螢幕解析度目測只有400px,如果頁面上真的有某一個頁面元素僅佔10%,也就是40px的話,肉眼幾乎是無法分辨的。實際情況應該會更糟糕,iPhone4的Safari預設是以980px來渲染網頁的。如果你在Chrome以案頭版的方式訪問stackoverflow,那麼結果會是這樣的:

體驗非常糟糕吧,所有的連結幾乎都無法準確點擊。那麼如何解決這個問題?

第一個辦法,放大頁面。

我們會很習慣的用手勢去放大頁面。但是要注意我們這裡做的僅僅是放大頁面,改變的是頁面的縮放(scale),效果與PC上瀏覽器的類似。但是沒有改變頁面的布局,此時用於渲染頁面配置的layout仍然是980px

第二個辦法是,改變布局。
比如下面一個頁面上有一張320px寬的圖片,如果我們以預設的980px去渲染的話,它會顯得過於窄小:

但如果我們可以將渲染它的布局設為320px的話,看上去就會好很多了,同時此時我們也未對頁面

進行縮放:

當然你也可以結合上一步,同時對頁面進行縮放:

不僅僅是放大,即使是在320px的像素下,我們也可以進行縮小:

迴歸到技術上,以上這些都可以通過viewport標籤來解決,比如說上面的需求,把布局設定為320px,同時進行1.5倍的縮放:

<meta name="viewport" content="width=320, initial-scale=1.5">
所見即所得 (WYSIWYG),需要設定的屬性在content以逗號分割開來,width表示頁面配置寬度,initial-scale代表頁面初始狀態的縮放比例,如果你不想讓使用者進行縮放,還可以添加user-scalable=no欄位來保證使用者無法進行縮放。

更重要的是,我們還可以無需指定特定寬度,通過設定width=device-width,指定布局寬度等於手機解析度寬度(但是我們不用關心手機分辨寬度是什麼)來更好的利用響應式設計。注意這裡的device-width表示手機的解析度寬度,而並非手機物理像素寬度。iPhone4在垂直狀態下物理像素寬度為640,這裡的device-width代表的則應該是它的dip像素320px。

給viewport標籤添加width=device-width適用於這樣一種情況:你在為行動裝置開發的響應式網頁時,你會面臨多重解析度情況,但是你又沒有必要使用到重量級的mediaquery,同時也為了避免手機瀏覽器使用案頭解析度寬度去渲染頁面, 同時這還能相容在手機橫握或者豎握的情況。 這樣讓你的響應式頁面能夠適用大多數的行動裝置。

寫到這裡我們可以做一個總結,viewport標籤的作用是什嗎?它能夠讓你撇開裝置的幹擾,告訴裝置你想用什麼樣的寬度渲染網頁。讓它聽命於你,而不是你聽命於他。

上面我們談到viewport有個半專業的名詞成為layout viewport,雖然它是一個非官方的詞彙,但是非常多的文章都引用了這個概念。layout viewport專用於頁面渲染的控制。還有一種viewport稱之為visual viewport,可以譯為可視視窗。兩種viewport的區分如下:

由此可以看出visual viewport就好比是瀏覽網頁的一個視窗,網頁正是這窗外的景色。當然我們還會遇見layout viewport與visual viewport大小相等的情況。比如像下面這樣:

這也就是我上面描述的width=device-width了。

番外篇:PPI和DPI使用的更多情境

在文章的開頭我有說PPI在不同上下文中的含義是不同的,如果你仍有好奇心,可以繼續往下閱讀。接下來我們談談Web以外的PPI含義。

首先我們要重申上面的結論,就談論顯示裝置的像素密度而已,PPI和DPI和一樣的概念,並且其中的像素pixel和點dots代指的都是物理像素。

如果你去查看一張JPG圖片的屬性時,你會發現有橫向或者縱向的以dpi為單位的屬性或者在Phototshop建立一份文檔時,要填寫一個以ppi為單位的屬性值:

這裡也存在被混用和混淆的地方。其實他們都表示列印時的解析度值。意為在列印時每英寸上的像素(也就是跟接近PPI,但我們更常用DPI)。這裡的英寸當然不再是螢幕像素了,而是紙張尺寸了。

PPI或者DPI對於圖片來說意味著什嗎?準確來說什麼都不意味著。 一張圖片只是存在相機或者硬碟裡的資料檔案而已,你能告訴我它有多少英寸長或者多少英寸寬嗎?只有當它被列印出來的時候才會涉及到列印媒介的尺寸,DPI才有意義。 如果你想讓圖片更豐富,唯一的辦法是增加圖片的像素,提升你的拍攝技巧。

當然在紙張上是沒有像素的概念。但我們可以去抽象的去想象它。假設有一張300x300像素的圖片。列印解析度的為30DPI,那麼最後列印出來尺寸為10x10英寸。假如列印時的DPI值為300DPI,那麼列印出來的尺寸則為1x1英寸。所以我們可以把DPI當做調節列印尺寸大小的手段。

那麼DPI值越高,圖片就越小就越清晰?當然也並非如此。如果你距離60厘米去觀看一張194DPI列印出來的圖片。你會沒法區分它到底是194DPI還是300DPI。因為人眼的解析度是有限的。這對顯示裝置同樣通用的。iPhon4的像素密度有326DPI,而New iPad的像素密度只有264DPI,New iPad的顯示效果會更差嗎?參考大多數人使用的距離和方式,其實眼睛得到的效果其實是無太大差異的。這也是為什麼大型顯示器或者戶外廣告DPI都不會很高,因為我們觀看他們的時候距離很遠,效果並非太差。

最後我們可以來看另一個情境的DPI:描述印表機的列印解析度:

當一張顯示器上的圖片列印在圖片上的時候,像素這個概念其實是我們想象出來的,更加實際的概念時是印刷裝置的每一個“點”:

當你嘗試去用放大鏡去查看彩色印刷物品上的圖片時,從小到大你看到的結果應該是這樣的:

為什麼會這樣?簡而言之,印刷的原理是通過半色調(halftone)技術,通過控制CMYK四種顏色點印刷時的每一個印刷點的大小,角度,間隙來類比出一種顏色的感覺:

比如當你以600DPI列印一張150PPI的圖片時,每一個像素應該包含16個點(600dots / 150pixels = 4)。

從上面我們已經知道PPI能夠決定印刷品物理尺寸的大小,印表機的DPI參數更是能進一步決定印刷體的好壞。我們用雩都在追求更高的DPI和PPI。

150dpi通常已經是被認為算的上是高品質的列印解析度了。新聞報紙使用的解析度通常是85dpi。戶外的廣告牌通常使用的是45dpi。但是因為距離的關係你不會覺得他們的印刷品質太差。

結尾

這篇文章我把移動開發中可能會涉及到的概念都做了一些涉及。在下篇中我將運用到這些概念,並且總結在行動裝置上的圖片載入方案。

參考文獻(已在文中引用的就不在此列舉了):
  • devicePixelRatio
  • Pixels per inch is just a tag
  • Configuring the Viewport
  • PPI vs. DPI: what’s the difference?
  • The Myth of DPI
  • DPI Myth
  • What is DPI?
  • Pixel Density: Pixels Per Inch (PPI) Explained
  • 轉自http://www.infoq.com/cn/articles/development-of-the-mobile-web-deep-concept

 

淺談移動Web開發(上):深入概念

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.