不同设备屏幕尺寸和DPR适配
為什么需要適配
目前市面上設備屏幕屬性十分多樣化(寬度和DPR并不一致),而作為設計和前端開發,無法為每個尺寸的設備單獨設計一套UI并將其轉為前端代碼,這不現實。所以我們需要一套方案來將一套設計稿完美呈現在不同尺寸的設備上。
設備的多樣性不止體現在設備屏幕尺寸上,還有屏幕的DPR也不同,有1,有2,有3等等。不同DPR的設備展示的視圖清晰度也不同,所以這套方案要考慮屏幕尺寸和屏幕清晰度這兩個因素。
一些基本概念
一個屏幕的DPR是根據屏幕的物理像素除以屏幕的設備獨立像素(也叫密度無關像素)得來的(DPR = 物理像素 / 設備獨立像素)。iphone6寬度的設備獨立像素是375,寬度的物理像素是750,那么就意味著DPR是2。這就意味著需要四個物理像素來描繪一個設備獨立像素,就像一個田(請忽略邊框)的形狀。
設備獨立像素又叫做密度無關像素,可以認為是系統中一個點,這個點可以是可以由程序使用的虛擬像素(如CSS的px),然后系統會將這個像素轉換為物理像素,在屏幕的DPR為2的設備上CSS的1px就會轉為4個物理像素。
屏幕密度(PPI),通常是計算每英寸有多少個像素(設備獨立像素),計算公式是:屏幕斜對角的像素數除以屏幕的英寸得出PPI的值。
對一開始適配問題做出一定程度的解釋
根據上面DPR解釋可以知道在DPR為2的屏幕上會使用四個設備像素來描述一個CSS像素。在這種情況下一張100*100的圖片在頁面上的尺寸也是100*100那么其實是200*200個物理像素來描繪這張圖片,很明顯圖片的像素是不夠的,這時候系統就會讓剩下的像素就近取色,這樣就造成了圖片的模糊,想要圖片不模糊要么提供一個200*200的圖片,要么將頁面上100*100的容器縮小到50*50。
在DPR為2的屏幕上高度的1px其實是由2個物理像素描繪的,所以該屏幕可以描繪的最小像素應該是0.5px,所以這個1px應該是0.5px才對。
怎么做適配
既然提出了問題那么就需要解決,解決方案主要來自手淘的flexibleJS,其原理就是適配不同屏幕尺寸主要用到了rem,而適配不同的DPR主要用到了<meta name="viewport" content="initial-scale=1/dpr"/>
不同屏幕尺寸
在CSS中單位使用rem,那么只要修改html的font-size那么這個頁面的尺寸都會隨之等比例改變。例如:
首先我們知道設計稿寬度例如750px,其中有個100px的正方形
其次我們也知道當前運行代碼的設備的屏幕寬度document.documentElement.clientWidth,這樣就可以算出來在當前設備下這個正方形的寬高
通過觀察上面設備下元素尺寸的計算公式 100px * document.documentElement.clientWidth / 750。可以簡化成 設計稿元素尺寸 * 某個系數,可以聯想到rem。這個單位后面的系數就是rem對應的font-size值。
所以在375屏幕尺寸下rem對應的font-size就是 375 / 750 等于 0.5px,0.5px * 100px 等于 50px。所以750下100單位在375設備下為50單位。
到這里我們得到公式 x = 元素在設計稿上的尺寸 * (設備寬度 / 設計稿寬度),其中 設備寬度 / 設計稿寬度是html的font-size值,也就是1rem。
但問題是瀏覽器有最小font-size的限制,目前算出來的1rem對于的font-size是0.5px,顯然小于最小font-size的限制。
所以我們要將1rem對應的font-size搞大點,修改下公式:
x = (元素在設計稿上的尺寸 / 100) * ((設備寬度 / 設計稿寬度) * 100)
將1rem對應的font-size變大之后,要將其調整回來,需要對設計稿上的尺寸再縮小對應倍數。
到這里我們就完成了一份設計稿適配不同尺寸設備的方案。
不同DPR
模糊主要是由于圖片像素不夠導致的,例如有一張100 * 100的圖片需要渲染在200 * 200的盒子中,因為圖片的10000個像素點需要鋪滿40000個像素的面積,就會導致圖片渲染的有些模糊,這個問題可以通過切2~3倍圖來解決。但是0.5像素的問題則需要使用頁面縮放來解決,因為dpr2的設備上可以渲染出來0.5px,而邏輯像素最小是1px。
對于適配不同設備DPR的高清方案思路如下:
這樣就可以保證一個物理像素對應一個邏輯像素,讓整個畫面看起來清晰很多。
function adapterHD (width = 750) {const dpr = window.devicePixelRatio || 1document.querySelector('meta[name="viewport"]').setAttribute("content", "width=device-width, initial-scale=" + 1 / dpr)const oneRem = Math.floor(document.documentElement.clientWidth / width * 100)document.querySelector('html').style = 'font-size: ' + (oneRem) + 'px' }因為首先設置了縮放,縮放后 documentElement.clientWidth就會放大 DPR倍,所以onRem沒有顯式乘以DPR。
到這里還有兩個問題需要解決:
flexibleJS
在引用上文提到的手淘的flexibleJS之后會自動設置html的font-size為75px,這時候的主要問題就是怎么將設計稿(一般都是750*1334)中的各個px值轉換為rem??梢宰约菏謩铀?#xff08;比較麻煩),可以使用編輯器插件,使用postcss插件等詳情見使用Flexible實現手淘H5頁面的終端適配
參考
移動端H5頁面高清多屏適配方案
使用Flexible實現手淘H5頁面的終端適配
viewports剖析
再聊移動端頁面的適配
移動端Web頁面適配方案
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的不同设备屏幕尺寸和DPR适配的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JS中与正则相关的方法
- 下一篇: web安全之CSRF