自适应需要解决的问题

  1. 屏幕像素大小不同,统一表现
  2. 画面比例不同,统一表现
  3. 浏览器字体最小限制,不可能无限等比缩小

自适应不成功的表现:
4. 画面出现拉伸压缩
5. 文字内容显示异常
6. 画面出现空白区域

自适应方案

方案一:%单位

作为一个css相对单位,其相对计算的对象不固定(并不是所有元素都相对于父元素宽高),会造成计算的复杂性

方案二:vw/vh

按照占据视宽(高)比例设计

vw/vh缺陷
一些图表的自适应方式需要特别处理

方案三:rem

css 相对单位,相对于根元素的 font-size 值的大小
将设计稿的单位转化为rem单位就可以实现等比例的自适应缩放
随窗口变化响应地调整根元素font size

;(function () {  let docEle = document.documentElement  let screenRatioByDesign = 16/9 // 相当于同时给出了宽高  function setHtmlFontSize() {    var screenRatio = docEle.clientWidth / docEle.clientHeight;    var fontSize = (       // 针对比例不对产生白边的优化      screenRatio > screenRatioByDesign        ? (screenRatioByDesign / screenRatio)        : 1    ) * docEle.clientWidth / 10; // 数值可根据实际换算比例调整    docEle.style.fontSize = fontSize.toFixed(3) + "px";  }  setHtmlFontSize()  window.addEventListener('resize', setHtmlFontSize)})();

px自动转化为rem:

  1. 使用 less / sass
  2. 相关插件 postcss-plugin-px2rem
    smart-rem (自动计算rem) 加 postcss-auto-rem (打包px转化为rem 比 px2rem)
    参考博客

rem 局限性
将根元素 fontsize 作为基准,属于一种hack行为;
rem的方案对于1920及以上分辨率屏幕来说基本适用,但当切换到1366*768等小分辨率时,由于浏览器默认最小字体为12px,所以会导致文字比理想效果更大, 而echarts生成的canvas图中单位是以固定px写死的,也会出现超出画布的问题

因此衍生另一种方案: scale缩放

方案四:transform.scale()

通过缩放可以保证字体和canvas一并完成缩放

// index.html;(function(win){  var bodyStyle = document.createElement('style')  bodyStyle.innerHTML=`body{width:1920px; height:1080px!important;}`  document.documentElement.firstElementChild.appendChild(bodyStyle)  function refreshScale(){    let docWidth = document.documentElement.clientWidth;    let docHeight = document.documentElement.clientHeight;    var designWidth = 1920,        designHeight = 1080,        widthRatio = docWidth / designWidth,        heightRatio = docHeight / designHeight; // 缩放比例     document.body.style = `transform:scale(${widthRatio},${heightRatio});transform-origin:left top;`;   // 应对浏览器 全屏切换前后 窗口因短暂滚动条问题出现未占满情况    setTimeout(function(){      var lateWidth= document.documentElement.clientWidth,        lateHeight = document.documentElement.clientHeight;      if(lateWidth===docWidth) return;      widthRatio = lateWidth/ designWidth      heightRatio = lateHeight/ designHeight      document.body.style = "transform:scale(" + widthRatio + "," + heightRatio + ");transform-origin:left top;"    },0)  }  refreshScale()  win.addEventListener("pageshow", function (e) {    if (e.persisted) { // 浏览器后退的时候重新计算      refreshScale()    }  }, false);  win.addEventListener("resize", refreshScale, false);})(window)

自己封装 Vue 组件
第三方 Vue 组件 v-scale-screen

scale() 的弊端
比例不对的情况下,画面可能会被压缩

其他方案

  • postcss-px-to-viewport(饿了么移动端做法)
    直接计算每个像素在设计稿中占据的%来输出vw,rem
    (转换rem但固定font size)
postcss-px-to-viewport -- vwpostcss-px-to-viewport -- rem

dpr 物理像素 与 设备像素比

  • rem + vw(网易移动端做法)
    vw表示根元素font size, 随后采用rem

  • lib-flexible 前淘宝做法 viewport被广泛支持后此法已被放弃


echarts 可封装 fontSize 来转换数据

function fontSize(res) {  let docEl = document.documentElement,    clientWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth  if (!clientWidth) return  let fontSize = clientWidth / 1920 // 此处 1920 为设计稿的宽度  return res * fontSize}

使用 fontSize() 包裹 echarts 各种尺寸的原数据