原理:
物理像素:
一個物理像素是顯示器(手機屏幕)上的最小物理顯示單元。
設備獨立像素:
設備獨立像素(密度無關像素),可以認為是計算機坐標系統(tǒng)中得一個點,這個點代表一個可以由程序使用的虛擬像素(比如: css像素),然后由相關系統(tǒng)轉換為物理像素。
設備像素比:
設備像素比(簡稱dpr)定義了物理像素和設備獨立像素的對應關系,它的值可以按如下的公式的得到:
設備像素比 = 物理像素 / 設備獨立像素 // 在某一方向上,x方向或者y方向
在javascript中,可以通過window.devicePixelRatio獲取到當前設備的dpr。
以iphone6為例子:
1、設備寬高為375×667,可以理解為設備獨立像素(或css像素)。
2、dpr為2,根據上面的計算公式,其物理像素就應該×2,為750×1334。

我們稱dpr大于1的屏幕為高清屏(retina)。
對于:
width: 2px;
height: 2px;
在不同的屏幕上(普通屏幕 vs retina屏幕),css像素所呈現的大小(物理尺寸)是一致的,不同的是1個css像素所對應的物理像素個數是不一致的。
在普通屏幕下,1個css像素 對應 1個物理像素(1:1)。 在retina 屏幕下,1個css像素對應 4個物理像素(1:4)。
引入原因:
retina下,border: 1px問題
那么retina顯示屏的優(yōu)勢在哪里,設計師為何覺得高清屏下(右圖)這個線條粗呢?明明和左右一樣的~

上圖中,對于一條1px寬的直線,它們在屏幕上的物理尺寸(灰色區(qū)域)的確是相同的,不同的其實是屏幕上最小的物理顯示單元,即物理像素,所以對于一條直線,iphone5它能顯示的最小寬度其實是圖中的紅線圈出來的灰色區(qū)域,用css來表示,理論上說是0.5px。
所以,設計師想要的retina下border: 1px;,其實就是1物理像素寬,對于css而言,可以認為是border: 0.5px;,這是retina下(dpr=2)下能顯示的最小單位。 然而,無奈并不是所有手機瀏覽器都能識別border: 0.5px;,ios7以下,android等其他系統(tǒng)里,0.5px會被當成為0px處理,那么如何實現這0.5px呢?
然而,無奈并不是所有手機瀏覽器都能識別border: 0.5px;,ios7以下,android等其他系統(tǒng)里,0.5px會被當成為0px處理,那么如何實現這0.5px呢?
1、簡單的做法
.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實在是不夠通用(如:圓角等),寫起來也麻煩。
2、推薦的做法
<meta name="viewport" content="width=640,initial-scale=0.5,maximum-scale=0.5, minimum-scale=0.5,user-scalable=no">
這樣,頁面中的所有的border: 1px都將縮小0.5,從而達到border: 0.5px;的效果。
縮放的公式:
var dpr = window.devicePixelRatio;
var ratio = 1 / dpr;
var content = 'width=device-width, initial-scale=' + ratio + ', user-scalable=no, minimum-scale=' + ratio + ',
maximum-scale=' + ratio;
viewport.setAttribute('content', content);
這樣頁面就根據dpr的值來進行對應的縮放。
然而,頁面scale,必然會帶來一些問題:
1、字體大小會被縮放
2、頁面布局會被縮放(如: div的寬高等)
多屏適配布局問題:
移動端布局,為了適配各種大屏手機,目前最好用的方案莫過于使用相對單位rem。
基于rem的原理,我們要做的就是: 針對不同手機屏幕尺寸和dpr動態(tài)的改變根節(jié)點html的font-size大小(基準值)。
對于M站:
因為UI從來是拿iphone6的標注來給前端,所以我們直接用iphone6的標準。
根據rem,iphone6下的font-size應該是 32px 得出一個比率稱為bRate = 750 / 32; bRate: 23.4275; 所以一切其他的手機屏幕都可以圍繞這個bRate設置font-siez基準值。
fontSize = document.documentElement.getBoundingClientRect().width / bRate
htmls.setAttribute('style', 'font-size: ' + fontSize + 'px');
這樣實現了根據不同的屏幕寬度和dpr來實現不同響應式布局,很好的解決了border: 1px問題,也真正用到了rem。
好處:
1、 border: 1px問題。
2、 解決了以前根據屏幕寬度來手動做適應的是問題,比如iphone4上展示兩個標簽,iphone6上展示4個標簽這種問題。
如果將rem轉為為px :
ipone6下 將 xxxrem 轉換為 px的方法 xxx * 32 即可
要求:
由于引入了rem,會對開發(fā)人員有一點點要求:
1、不能在html.tpl中的 styl里面寫 px,所有的style都寫在樣式表里面。
不允許:
<p style=”height: 40px;width: 40px;”> </p>
<img src=”xxx” width=”120”, height=”130”>
推薦:
<p class=”setHeight”></p>
<img src=”xxx” class=”myImg”>
2、不能在js中的寫px,所有的位置計算,都以一個dom為基準計算,不允許平白無故寫px。
不允許:
$(‘.mydom’)
.css(
{ height: ‘40px’ }
);
if ($(‘.myDom’).height > 100)
推薦:
$(‘.mydom’).addClass(‘setHeight’);
if ($(‘.myDom’).height > $(‘.otherDom’).height)
3、不推薦在html里面拼大量的字符串,如果需要前端渲染模板,不推薦寫在Js里面,而是用artTemplate進行渲染。
如果只有一兩行的html話
不允許:
var s = ‘<p style=”height: 30px”></p>’;
推薦:
var s =’<p class=”myStyle”></p>’
不兼容問題:
1、富文本:
富文本中可以自己定義px,會造成部分被縮放的問題,所以建議凡是引用富文本的地方建議進行過濾處理。
過濾函數 M1,M2 common/function/transToRem.js
2、播放器:
由于每個手機原生的H5 video標簽的播放器都不一樣,所以不推薦有播放器的頁面進行自適應縮放。
(會有播放進度條和播放按鈕過被壓縮過小的問題,如果PM接受可以用縮放)。
3、嵌入外部網頁的iframe
如果要嵌入主站的iframe或者別的網站的iframe的話(子頁面沒設置fontSize的話),也不推薦使用縮放。
這種頁面M站有 引用百家云SDK播放器、百度地圖。
開關:
模板:針對上述情況,在M1、M2中設置了開關,只需要在入口模板中的

加{{$isNeedScale = false}}
js: TODO: 暫時還沒提取,會提取一個公共js來判斷js是否被縮放開關。
M2的react TODO: 暫時還沒提取,會提取一個公共js來判斷js縮放開關。