一些像素概念
-
物理像素:即實際的每一個物理像素,也就是移動設備上每一個物理顯示單元(點) -
設備邏輯像素( css
中的px
):可以理解爲一個虛擬的相對的顯示塊,與物理像素有着一定的比例關係,也就是下面的設備像素比 -
設備像素比( dpr
):= 物理像素 / 設備獨立像素(px
)
如果
dpr
爲1
的話,那麼1px = 1物理像素
,x
軸y
軸加起來就是1
如果
dpr
爲2
的話,那麼1px = 2
物理像素,x
軸y
軸加起來就是4
以此類推
在js中可以通過
window.devicePixelRatio
獲取當前設備的dpr
。
這裏說明一下,無論dpr
多大,1px
的大小通常來說是一致的,這也就意味着,隨着dpr
的增大,物理像素點會越來越小,這樣才能容納更多的物理像素,才能更高清,更retina
說完基本概念,來說一下幾個問題:
retina屏圖片模糊
首先普及一下位圖像素:一個位圖像素是圖片的最小數據單元,每一個單元都包含具體的顯示信息(色彩,透明度,位置等等)
那爲什麼在dpr高的retina屏上反而會模糊呢?看圖~
在
1dpr
的屏幕上,位圖像素和物理像素一一對應沒什麼問題,但是在retina
屏上,由於一個px
由4
個甚至更多的物理像素組成,並且單個位圖像素不能進一步分割,所以會出現就近取色的情況,如果取色不均,那麼就會導致圖片模糊。
對於這種情況,只能採用
@2x
、@3x
這樣的倍圖來適配高清展示,這樣側向說明了爲什麼照着iphone6
做的ui
稿不是375
,而是750
的問題。
雖然這樣在dpr
爲1
的屏幕上會導致1
個物理像素上有4
個位圖像素,但是這種情況的取色算法更優,影響不大,不做討論。
1px的粗細問題
由於
1px
的實際大小是一樣的,只是裏面的物理像素數量不同,所以如果直接寫1px
是沒問題的,不會出現粗細不同的情況,但是這樣一來retina
的優勢也rem
的作用也就沒了,其實還是dpr
的問題,dpr
爲1
,那麼1px
就是一個物理像素,但是在retina
中。1px
實際可能有4
、9
個物理像素,ui
想要的其實是1
個物理像素,而不是1px,不過由於不是素所有的手機都能適配0.x
,所以曲線救國,採用scale
縮放或者設置meta
都可以
viewport
三個概念
-
layout viewport
-
visual viewport
-
ideal viewport
layout viewport
最開始,
pc
上的頁面是無法再移動端正常顯示的,因爲屏幕太小,會擠作一團,所以就有了viewport
的概念,又稱佈局視口(虛擬視口),這個視口大小接近於pc
,大部分都是980px
visual viewport
有了佈局視口,還缺一個承載它的真是視口,也就是移動設備的可視區域-視覺視口(物理視口),這個尺寸隨着設備的不同也有不同。這樣在視覺視口中創建了一個佈局視口,類似
overscroll:scroll;
這樣,可以通過滾動拖拽、縮放擴大進行較好的訪問體驗
ideal viewport
像上面的體驗在早些年可能比較多,但是近幾年幾乎很少了,還是歸咎於用戶體驗,所以,我們還需要一個視口-理想視口(同樣是虛擬視口),不過這個理想視口的大小是等於佈局視口的,這樣用戶就能得到更好的瀏覽體驗。
一個特性
viewport
有六種可以設置的常用屬性:
-
width
:定義layout viewport
的寬度,如果不設置,大部分情況下默認是980
-
height
:非常用 -
initial-scale
:可以以某個比例將頁面縮放\放大,你也可以用它來設置ideal viewport
:
<meta name='viewport' content='initial-scale=1' />
-
maximum-scale
:限制最大放大比例 -
minimum-scale
:限制最小縮小比例 -
user-scalable
:是否允許用戶放大\縮小頁面,默認爲yes
rem適配方案
先說原理,通過
meta
修正1px
對應的物理像素數量,在根據統一的設計稿來生成html
上的動態font-size
,根據dpr
構造字體等誤差較大的樣式的mixin
// 第一版:
function initRem() {
const meta = document.querySelector('meta[name="viewport"]');;
const html = document.documentElement;
const cliW = html.clientWidth;
const dpr = window.devicePixelRatio || 1;
meta.setAttribute('name', 'viewport');
meta.setAttribute(
'content',
`width=${cliW * dpr}, initial-scale=${1 /
dpr} ,maximum-scale=${1 / dpr}, minimum-scale=${1 /
dpr},user-scalable=no`
);
html.setAttribute('data-dpr', dpr);
// 這樣計算的好處是,你可以直接用ui的px/100得到的就是rem大小,方便快捷,無需mixin
html.style.fontSize = 10 / 75 * cliW * dpr + 'px';
}
initRem();
window.onresize = window.onorientationchange = initRem();
對於引入的第三方ui組件,需要使用px2rem轉換工具去做整體轉換,比如
postcss-pxtorem
:https://github.com/cuth/postcss-pxtorem
回覆“加羣”與大佬們一起交流學習~
點擊“閱讀原文”查看 100+ 篇原創文章
本文分享自微信公衆號 - 前端自習課(FE-study)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。