大屏适配方案
前言
基于现目前所做数据可视化项目的不同分辨率兼容需求总结以下适配几种方案供参考。 通常而言数字大屏指的是1920*1080分辨率下的电视大屏,用于图表化的展示关键数据,然而项目有可能是在笔记本上或其它分辨率下的设备上运行,演示,测试。
一、一些前提概念
1.1 常见大屏分辨率
- 1366 * 768 : 普通液晶显示器
- 1920 * 1080: 高清液晶显示器
- 2560 * 1440: 2K高清显示器
- 4096 * 2160: 4K高清显示器
- 1280 * 720: 笔记本(1920*1080分辨率下系统默认推荐150%缩放比产生的尺寸。。。。)
1.2 设备像素
viewport
: 视窗=浏览器窗口的宽高物理像素(设备像素)
: 屏幕显示分辨率像素,每个像素可以根据操作系统设置自己的颜色 和亮度设备独立像素(dip)
:密度无关像素,可以认为是计算机坐标系统中的一个点,可用于区分视网膜设备还是非视网膜设备css像素(DIPs)
: 主要用在浏览器上,一般情况下,css像素称为与设备无关的像素屏幕密度
: 设备表面上存在的像素数量(PPI)设备像素比(dpr)
: 定义了物理像素和设备独立像素的对应关系,设备像素比=物理像素/设备独立像素
二、适配痛点
- 设计稿按照1920*1080的分辨率,16:9的比例设计, 实际开发中,document窗口不足16:9(高度减掉顶部tab及导航栏,地址栏等)
- 不同分辨率:实际应用场景中,显示场景不同,不能固定写死px单位
- 不同比例:不同的显示器宽高比与设计稿不一致
- 由于大屏数据可视化项目通常用于放在电视或广告屏上展示用,而不允许出现滚动条
三、关于rem
熟悉移动端的自适应方案的朋友对 rem 适应方案,肯定不陌生,最出名的就是阿里的 手淘lib-flexible 方案。
- rem (font size of the root element),是 css3 的引入的一个大小单位。即相对于根元素的 font-size 值的大小。所谓根元素在网页里一般就是 html.
- 举例如下:
html{ font-size:20px; } test1 { width: 1.4rem; //1.4 × 20px = 28px } test2 { height: 2.4rem; //2.4 × 20px = 48px }
- 通常如果应用场景只涉及16:9比例下,1920*1080分辨率屏幕的话,使用rem来自动计算即可实现不同大小屏幕的适配
四、关于px2rem
在采用rem作为适配方案时,避免不了将设计稿中的px单位转化为rem单位,开发过程中如果每个值都手动计算免不了麻烦,通常作法:
- 使用scss或less 函数进行计算
- webpack结合postcss-px2rem自动计算
- postcss 一种对css编译的工具,类似babel对js的处理,通过它的插件生态来实现各种功能转换,如:autoprefixer(. 自动补全浏览器前缀), px2rem(自动将px转换为rem)
这里对px2rem配置说明如下: - postcss-plugin-px2rem: 作为postcss的经典插件之一,用于自动转换px为rem postcss-px2rem文档
- 安装依赖:
npm i postcss-plugin-px2rem -D
- 配置vue.config.js
css: { loaderOptions: { postcss: { plugins: [ require('postcss-plugin-px2rem')({ rootValue: 100, //换算基数, 默认100 ,这样的话把根标签的字体规定为1rem为50px,这样就可以从设计稿上量出多少个px直接在代码中写多上px了。 unitPrecision: 5, //允许REM单位增长到的十进制数字。 propWhiteList: [], //默认值是一个空数组,这意味着禁用白名单并启用所有属性。 propBlackList: [], //黑名单 exclude: /(node_module)/, //默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值 selectorBlackList: [], //要忽略并保留为px的选择器 ignoreIdentifier: false, //(boolean/string)忽略单个属性的方法,启用ignoreidentifier后,replace将自动设置为true。 replace: true, // (布尔值)替换包含REM的规则,而不是添加回退。 mediaQuery: false, //(布尔值)允许在媒体查询中转换px。 minPixelValue: 3 //设置要替换的最小像素值(3px会被转rem)。 默认 0 }), ] } } }
五、 css3缩放scale
rem的方案对于1920及以上分辨率屏幕来说基本适用,但当切换到1366*768等小分辨率时,由于浏览器默认最小字体为12px,所以会导致文字比理想效果更多大, 而echarts生成的canvas图中单位是以固定px写死的,也会出现超出画布的问题,因此衍生第二种方案: scale缩放
- 思路:浏览器body设置为设计稿宽高即1920*1080, 动态根据实际宽高对body的width,height进行缩放,从而实现内容缩放
- body固定宽高:
body{ width: 1920px; height: 1080px; }
- 动态获取实际文档宽高并设置body缩放系数
// 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)
- 经过如上设置后,在项目中直接使用设计稿中px单位进行开发即可,当然这也有一个弊端,在非设计稿比例(16:9)下,界面会被压缩,但它的优势在于会对body内所有元素进行缩放,从而不会让echarts图表超出画布
六、根据尺寸媒体查询适配
<style lang="scss"> // 适配大屏宽度3840,可以是区间 @media screen and (min-width: 3840px){ $oneVw: 21.6; @function getvw($data) { @return $data/$oneVw * 1vh; } .main { height: getvw(480); } } </style> <style lang="scss"> // 根据宽高比适配 @media screen and (min-aspect-ratio:16/32){ $oneVw: 10.8; @function getvw($data) { @return $data/$oneVw * 1vh; } .main { height: getvw(480); } } </style>