1. 程式人生 > 其它 >移動端適配:淘寶和唯品會rem方案原理

移動端適配:淘寶和唯品會rem方案原理

0 tl;dr

其實也沒啥原理,就是一個比例問題。

1 前置知識

裝置獨立畫素(DIP):一種抽象的畫素,與實際物理畫素之間的比值就是DPR。簡而言之,一個裝置獨立畫素實際上可以由\(1*1\),\(2*2\),\(3*3\)...等任意多個物理畫素來表現,取決於裝置的設定。而應用一般並不需要實際與物理裝置打交道,只與裝置獨立畫素打交道。

接下來討論的適配問題都是關於裝置獨立畫素的。

2 淘寶適配方案

定義幾個變數:設計稿寬度x, 設計稿中任意邊長a, 最終裝置獨立畫素寬度 d, a實際渲染的長度a'

適配的最終目的,就是要在裝置中渲染出a'。

那麼問題轉換為找出a -> a'的等式。

不難得出一個等式:

\[ a'=\frac{a}{x}d \]

由於最終的d是動態的(不是一個固定值,因裝置而異),所以想要尋找一個辦法,使得該等式不受d的影響(即不需要對每個值都手動計算一次轉換)。換句話說,計算一箇中間量,在真正得到d之後再計算出真正的值。

淘寶的方案引入了一個基礎值y=375,當然,這個基礎值可以是任意的值。引入基礎值後,上述等式可以改寫為

\[a'=\frac{a}{x}*y*\frac{d}{y} \]

這裡的\(\frac{d}{y}\)就是\(\frac{document.documentElement.clientWidth}{375}\)

接下來可以將\(\frac{a}{x}*y\)

作為中間量,表示相對的長度;而\(\frac{d}{y}\)作為單位,動態新增。這裡html的rem剛好是這樣的單位,所以可以將\(\frac{d}{y}\)設定為html的font-size值,其他的長度都設定為相對的中間量\(\frac{a}{x}*y\) rem,最終計算時,自動乘以這個font-size值就OK。

\(\frac{d}{y}\)往往都不會很大(就算是d=1920,在y=375的時候也只有5.12),又由於font-size屬性不支援小於12px的值,所以乘以了100以避免被強制提升到12px,另外也方便計算。換句話說,前面對應地要除以100。等式改寫為:

\[ a'=\frac{a}{x}*y*\frac{1}{100}*\frac{d}{y}*100 \]

根據這個式子,我們可以很快拆出我們認識的部分:

\[\begin{cases} htmlFontSize = \frac{d}{y}*100\\ pxInCSS = \frac{a}{x}*y*\frac{1}{100} \end{cases} \]

這個式子顯而易見地回答了什麼時候可以不經修改使用原始畫素的1/100 rem:當\(x=y\)時。

3 唯品會方案

還是同樣的前設:

設計稿寬度x, 設計稿中任意邊長a, 最終裝置獨立畫素寬度 d, a實際渲染的長度a'

\[ a'=\frac{a}{x}d \]

這裡唯品會的做法是:引入一個完全固定的中間量10,則上式改為

\[ a'=\frac{a}{x} * 10 * \frac{d}{10} \]

拆分之後的結果是

\[\begin{cases} htmlFontSize = \frac{d}{10}\\ pxInCSS = \frac{a}{x}*10 \end{cases} \]

4 總結

如果遮蔽掉rem的設定,只看設計稿落實的話,淘寶方案可以看作是比例*3.75 rem(如果確定用375作為除數的話就是乘以\(\frac{1}{(設計稿寬/375 )* 100}\)。比如設計稿寬375,任意長度直接除以100;設計稿寬750,任意長度直接除以200,依此類推)。

唯品會可以看作是比例*10 rem。

淘寶方案雖然理解起來繞一點,但是用起來相當方便,特別是當設計稿寬度是基數的整數倍時,幾乎沒有小數。而唯品會方案相反,理解容易,但是可能處處都有無限迴圈小數。當然,應用上工具的話,這兩者都沒有區別,工具可以幫忙自動轉換。