摘 要:開發(fā)者在開發(fā)HTML5應(yīng)用時必須考慮所有屏幕尺寸和分辨率類型的應(yīng)用場景,為移動應(yīng)用做屏幕尺寸和分辨率的適配工作。
隨著移動和HTML5的持續(xù)火熱,移動市場涌現(xiàn)出了大量基于HTML5開發(fā)的移動APP。由于移動市場的高速發(fā)展,移動設(shè)備的快速更新,使得市場上出現(xiàn)了種類繁多具有各種屏幕尺寸和分辨率的移動設(shè)備,開發(fā)者在開發(fā)HTML5應(yīng)用時就必須考慮所有屏幕尺寸和分辨率類型的應(yīng)用場景,為移動應(yīng)用做屏幕尺寸和分辨率的適配工作。
想要為移動應(yīng)用做屏幕適配首先要了解一些概念。物理像素,即屏幕上的最小顯示單元;設(shè)備獨立像素,即由程序使用的虛擬像素(如CSS中的px);設(shè)備像素比,設(shè)備像素比 = 物理像素 / 設(shè)備獨立像素,定義了物理像素與設(shè)備獨立像素間的對應(yīng)關(guān)系,簡稱dpr(device pixel ratio)。在不同屏幕上,CSS像素呈現(xiàn)的大小(物理尺寸)是一致的,不同的是一個CSS像素對應(yīng)的物理像素個數(shù)是不同的。舉例來講,普通屏幕的每個像素點與CSS中定義的像素點大小相同,但是蘋果的retina屏幕一個CSS像素對應(yīng)4個物理像素。因此,在開發(fā)應(yīng)用時就需要對不同屏幕(高清和非高清)進行區(qū)分處理。就一張普通的圖片(PNG、JPG、GIF等)來講,其最小的數(shù)據(jù)單元稱為位圖像素。理論上,一個位圖像素對應(yīng)一個物理像素,這樣圖片才能完美的清晰展示,但是對于高清屏幕(Retina)就會出現(xiàn)位圖像素點不夠的情況,這樣會導(dǎo)致圖片模糊。遇到這種情況,通常要準(zhǔn)備兩張圖片,如一張200×300(CSS px),并提供一張400×600的高清圖片,這樣位像素點就是原來的4倍,在retina屏幕下正好與其物理像素點一一對應(yīng),圖片自然就清晰了。當(dāng)然,具體要加載那種圖片是有dpr來判斷的,在JavaScript中,可以通過window.devicePixelRatio獲取到當(dāng)前設(shè)備的dpr,在css中,可以通過-webkit-device-pixel-ratio,-webkit-min-device-pixel-ratio和 -webkit-max-device-pixel-ratio進行媒體查詢,對不同dpr的設(shè)備,做一些樣式適配。與圖片問題類似,高清屏幕還存在一種“失真”的問題,即border:1px問題。對于border:1px在所有屏幕中的物理大小其實是相同的(下圖灰色區(qū)),但這怎能體現(xiàn)出高清呢?對于retina屏幕來說,一個 CSS像素由4個物理像素組成,因此其最細的線條并不是1px,而是0.5px,如下圖紅色框。而一般情況下設(shè)計師想要的retina下border: 1px,其實就是1物理像素寬,這種更細粒度的劃分也帶來的視覺上的高清。
當(dāng)然,除了高清上的適配,還存在著屏幕大小上的適配,即頁面布局問題。目前解決該問題最好用的方案是使用相對單位(rem),主要工作就是針對不同手機屏幕尺寸和dpr動態(tài)的改變根節(jié)點html的font-size大小(基準(zhǔn)值)。rem=document.documentElement.clientWidth * dpr / 10,乘以dpr是因為頁面有可能為了實現(xiàn)1px border縮放1/dpr倍(如果沒有,dpr=1),除以10是為了取整,方便計算。可以通過JavaScript來實現(xiàn),使用公式計算出基準(zhǔn)值rem,然后寫入樣式,代碼如下:
var dpr, rem, scale;
var docEl = document.documentElement;
var fontEl = document.createElement('style');
var metaEl = document.querySelector('meta[name="viewport"]');
scale = 1 / dpr;
dpr = win.devicePixelRatio || 1;
rem = docEl.clientWidth * dpr / 10;
// 設(shè)置viewport,進行縮放,達到高清效果
metaEl.setAttribute('content', 'width=' + dpr * docEl.clientWidth + ',initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale + ',user-scalable=no');
// 設(shè)置data-dpr屬性,留作的css hack之用
docEl.setAttribute('data-dpr', dpr);
// 動態(tài)寫入樣式
docEl.firstElementChild.appendChild(fontEl);
fontEl.innerHTML = 'html{font-size:' + rem + 'px!important;}';
// 給js調(diào)用的,某一dpr下rem和px之間的轉(zhuǎn)換函數(shù)
window.rem2px = function(v) {
v = parseFloat(v);
return v * rem;
};
window.px2rem: function(v) {
v = parseFloat(v);
return v / rem;
};
window.dpr = dpr;
window.rem = rem;
那么如何在CSS編碼中實現(xiàn)真實布局呢?舉例來講,一個針對iPhone6(rem=375 * 2 / 10 = 75)的高清視覺稿750×1334px,采用上面JS代碼方案。如果有一塊750×300px的div,用less這樣寫:
// 例如: .px2rem(height, 80);rem在iphone6時為75
.px2rem(@name, @px , @rem){
@{name}: @px / @rem * 1rem;
}
.px2rem(width, 750);
.px2rem(height, 300);
轉(zhuǎn)化成HTML就變成了10×4rem,再經(jīng)過0.5的縮放,在屏幕中的實際現(xiàn)實的是375×150px,這樣就動態(tài)的生成了div的大小完成了適配過程。
HTML 5已成為移動發(fā)展的趨勢,很好的解決屏幕適配問題只是其眾多亮點之一,但是它也存在著性能不如原生應(yīng)用之類的問題,相信隨著其不斷發(fā)展完善,HTML 5未來一定會成為前端的新標(biāo)準(zhǔn)。