flexible.js原理解析

flexible原理解析

github倉庫:github.com/amfe/lib-fl…javascript

使用方法

安裝

npm i -S amfe-flexible
複製代碼
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<script src="./node_modules/amfe-flexible/index.js"></script>
複製代碼

原理解析

源碼只有短短43行,講解分爲兩部分:代碼中的註釋和與原理總結html

源碼註釋

// 首先是一個當即執行函數,執行時傳入的參數是window和document
(function flexible (window, document) {
  var docEl = document.documentElement // 返回文檔的root元素
  var dpr = window.devicePixelRatio || 1 
  // 獲取設備的dpr,即當前設置下物理像素與虛擬像素的比值

  // 調整body標籤的fontSize,fontSize = (12 * dpr) + 'px'
  // 設置默認字體大小,默認的字體大小繼承自body
  function setBodyFontSize () {
    if (document.body) {
      document.body.style.fontSize = (12 * dpr) + 'px'
    } else {
      document.addEventListener('DOMContentLoaded', setBodyFontSize)
    }
  }
  setBodyFontSize();

  // set 1rem = viewWidth / 10
  // 設置root元素的fontSize = 其clientWidth / 10 + ‘px’
  function setRemUnit () {
    var rem = docEl.clientWidth / 10
    docEl.style.fontSize = rem + 'px'
  }

  setRemUnit()

  // 當頁面展現或從新設置大小的時候,觸發從新
  window.addEventListener('resize', setRemUnit)
  window.addEventListener('pageshow', function (e) {
    if (e.persisted) {
      setRemUnit()
    }
  })

  // 檢測0.5px的支持,支持則root元素的class中有hairlines
  if (dpr >= 2) {
    var fakeBody = document.createElement('body')
    var testElement = document.createElement('div')
    testElement.style.border = '.5px solid transparent'
    fakeBody.appendChild(testElement)
    docEl.appendChild(fakeBody)
    if (testElement.offsetHeight === 1) {
      docEl.classList.add('hairlines')
    }
    docEl.removeChild(fakeBody)
  }
}(window, document))

複製代碼

原理總結

首先有幾個名詞須要解釋一下:前端

rem

以rem爲單位,其值是相對root html元素,與em這個相對於父元素的單位不一樣。java

rem是flexible這套適配方案的核心node

rem的詳情點擊此處git

Element​.clientWidth

Element​.clientWidth

如上圖所示,clientWidth是元素內部的寬度,包括padding,但不包括border,margin和垂直的滾動條github

Element​.clientWidth的詳情點擊此處npm

Document​.document​Element

Document​.document​Element 返回文檔的root元素,HTML文檔的元素瀏覽器

window.devicePixelRatio

window.devicePixelRatio返回當前顯示設備下物理像素與設備獨立像素的比值,一樣也能夠解讀爲一個設備獨立像素是有幾個物理像素來展現的。app

物理像素

物理像素是組成成像傳感器的最基礎單元的尺寸。

設備獨立像素 - Device Independent Pixels(dip)

設備獨立像素是一個物理測量單位,是操做系統層面設置的虛擬像素。對於前端來講是定值。

當頁面設置了,那document.documentElement.clientWidth就等於設備獨立像素的寬度

window.devicePixelRatio的詳情點擊此處

總結

首先經過設置meta,其主要做用的是width=device-width,使用這個以後,document.documentElement.clientWidth就等於設備獨立像素的寬度。

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
複製代碼

而後給root元素設置fontSize爲document.documentElement.clientWidth的十分之一,這樣1rem就等於document.documentElement.clientWidth/10,以此作適配。

rem並不是是完美的適配方案,使用了rem,最後渲染時仍是轉換成px,這時小數部分就四捨五入,有些結果並非咱們想要的。

meta viewport

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
複製代碼

meta標籤中的viewport做用是什麼呢?

viewport,在瀏覽器環境中,表示當前的瀏覽器的可視區域,正在被瀏覽的頁面,在這塊區域中被展現。

viewport,設置了viewport的初始尺寸,僅可以使用在移動端。

可能的子值 描述
width 整數 或 device-width 定義viewport的寬度,用於展現網頁
height 整數 or device-height 定義viewport的高度,但幾乎未被瀏覽器使用
initial-scale 一個大於0.0小於10.0的數字 定義了設備尺寸與viewport的比例
maximum-scale 一個大於0.0小於10.0的數字 定義了能夠放大的最大值,大於等於minimum-scale,且瀏覽器的設置能夠忽略它,iOS10+默認忽略它
minimum-scale 一個大於0.0小於10.0的數字 定義了能夠縮小的最小值,小於等於maximum-scale,且瀏覽器的設置能夠忽略它,iOS10+默認忽略它
user-scalable yes 或 no no,用戶不能縮放;yes,用戶能夠縮放,但瀏覽器的設置能夠忽略它,iOS10+默認忽略它
相關文章
相關標籤/搜索