自适应需要解决的问题
- 屏幕像素大小不同,统一表现
- 画面比例不同,统一表现
- 浏览器字体最小限制,不可能无限等比缩小
自适应不成功的表现:
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:
- 使用 less / sass
- 相关插件 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, 随后采用remlib-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 各种尺寸的原数据