可视化大屏自适应方案
Posted J.P_P
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了可视化大屏自适应方案相关的知识,希望对你有一定的参考价值。
前言
最近在做可视化大屏项目,遇到自适应的问题,这边做下记录。
方案
方案一:利用css的transform属性构造组件以及设计百分比以及scal()方法:
第一步:先写一个组件,width = 100vw,height = 100%,作为大屏展示的背景
<template>
<div class="screen-large">
<div class="screen-large_wrap">
<slot />
</div>
</div>
</template>
<style lang="scss">
.screen-large
width: 100vw;
min-height: 100%;
max-height: 100vh;
overflow: hidden;
background: #567789;
</style>
第二步:根据设计同学提供的设计图可以计算出每部分区域的百分比,例如总尺寸是w*h,其中一个图标宽高是w1 * h1,实现常规切图,此时由1–>2可得:
<template>
<div class="screen-large">
<div class="screen-large_wrap" :style="style">
<slot />
</div>
</div>
</template>
<script>
export default
name: 'Screen',
data()
return
style:
width: `$this.wpx`,
height: `$this.hpx`,
transform: 'scale(1) translate(-50%, -50%)', // 默认不缩放,垂直水平居中
,
;
,
props:
w: // 设计图尺寸宽
type: Number,
default: 1920,
,
h: // 设计图尺寸高
type: Number,
default: 1080,
,
,
;
</script>
<style lang="scss">
.screen-large
width: 100vw;
min-height: 100%;
max-height: 100vh;
overflow: hidden;
background: #567789;
.screen-large_wrap
transform-origin: 0 0;
position: absolute;
top: 50%;
left: 50%;
padding: 18px 64px;
</style>
第三步:基于第二步,需要根据大屏具体尺寸计算缩放比例,以及设置缩放比例,需要注意的是,绑定resize事件一定别忘了防抖,页面销毁别忘了移除监听事件:
<template>
<div class="screen-large">
<div class="screen-large_wrap" :style="style">
<slot />
</div>
</div>
</template>
<script>
export default
name: 'Screen',
data()
return
style:
width: `$this.wpx`,
height: `$this.hpx`,
transform: 'scale(1) translate(-50%, -50%)', // 默认不缩放,垂直水平居中
,
;
,
props:
w: // 设计图尺寸宽
type: Number,
default: 1600,
,
h: // 设计图尺寸高
type: Number,
default: 1200,
,
,
mounted()
this.setScale();
this.onresize = this.debounce(() => this.setScale(), 100);
window.addEventListener('resize', this.onresize);
,
methods:
// 防抖
debounce(fn, t)
const delay = t || 500;
let timer;
// eslint-disable-next-line func-names
return function ()
// eslint-disable-next-line prefer-rest-params
const args = arguments;
if (timer)
clearTimeout(timer);
const context = this;
timer = setTimeout(() =>
timer = null;
fn.apply(context, args);
, delay);
;
,
// 获取缩放比例
getScale()
const w = window.innerWidth / this.w;
const h = window.innerHeight / this.h;
return w < h ? w : h;
,
// 设置缩放比例
setScale()
this.style.transform = `scale($this.getScale()) translate(-50%, -50%)`;
,
,
beforeDestroy()
window.removeEventListener('resize', this.onresize);
,
;
</script>
<style lang="scss">
.screen-large
width: 100vw;
min-height: 100%;
max-height: 100vh;
overflow: hidden;
background: #567789;
.screen-large_wrap
transform-origin: 0 0;
position: absolute;
top: 50%;
left: 50%;
padding: 18px 64px;
</style>
引用方式和最终呈现效果
非常规尺寸可能会更具长宽比导致左右或者上下留出空白,这里需要采用@media
媒介查询解决
方案二:大屏vw和vh适配方案:
按照设计稿的尺寸,将px
按比例计算转为vw
和vh
。
假设设计稿尺寸为1920*1080
(做之前一定问清楚UI设计稿的尺寸),即: 网页宽度=1920px,网页高度=1080px;我们都知道,网页宽度=100vw,网页宽度=100vh。
所以,在1920x*1080px的屏幕分辨率下1920px = 100vw,1080px = 100vh。这样一来,以一个宽300px和200px的div来说,其作所占的宽高,以vw和vh为单位,计算方式如下:
vwDiv = (300px / 1920px ) * 100vw;
vhDiv = (200px / 1080px ) * 100vh;
所以,就在1920*1080
的屏幕分辨率下,计算出了单个div的宽高当屏幕放大或者缩小时,div还是以vw和vh作为宽高的,就会自动适应不同分辨率的屏幕。
但是每次都手动计算时不现实的,所以,需要封装一个方法,让它帮我自动计算:
// 使用scss的math函数,https://sass-lang.com/documentation/breaking-changes/slash-div
@use "sass:math";
//默认设计稿的宽度
$designWidth: 1920;
//默认设计稿的高度
$designHeight: 1080;
//px转为vw的函数
@function vw($px)
@return math.div($px , $designWidth) * 100vw;
//px转为vh的函数
@function vh($px)
@return math.div($px , $designHeight) * 100vh;
vue.config.js(只展示了与本方法有关的配置)
module.exports =
...,
css:
loaderOptions:
//全局配置utils.scss,详细配置参考vue-cli官网
sass:
prependData: '@import "@/styles/utils.scss";',
,
,
;
在**.vue**
文件中使用
<script>
export default
name: "Index",
</script>
<style lang="scss" scoped="scoped">
/* 直接使用vw和vh函数,将像素值传进去,得到的就是具体的vw vh单位*/
.chart-wrapper
width: vw(400);
height: vh(300);
font-size: vh(16);
background-color: black;
margin: vw(20);
border: vh(2) solid red;
</style>
特殊的使用情况
有的时候可能不仅在.vue
文件中使用,比如在js中动态创建的DOM元素
它可能是直接渲染到html里面的
let oDiv = document.createElement('div')
document.body.appendChild(oDiv)
这样的话,我用了以下两种处理方式,来给创建的div设置样式
1. 定义一些全局的class
新建一个global.scss
文件,在main.js
中引入
global.scss
.global-div
width: vw(300);
height: vw(200);
background-color: green;
main.js
import './styles/global.scss'
使用时,给创建的div设置className,
let oDiv = document.createElement('div')
oDiv.className = "global-div"
还有echarts图表可能会需要自适应字体
/* Echarts图表尺寸自适应 */
export const fitChartFontSize = (size, defaultWidth = 1920) =>
let clientWidth = window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;
if (!clientWidth) return size;
let scale = (clientWidth / defaultWidth);
return Number((size*scale).toFixed(3));
使用
// Options.js
//坐标轴刻度标签的相关设置
yAxis:
axisLabel:
textStyle:
color: "rgba(255, 255, 255, 0.3)"
,
fontSize: fitChartFontSize(10)
,
,
2. 第三方自动适配插件库Postcss + 转换成vw的插件
一、安装postcss
npm install postcss -S
二、使用npm/yarn安装postcss插件
$ npm install postcss-px-to-viewport --save-dev
$ yarn add -D postcss-px-to-viewport
配置参数
//默认参数options:
unitToConvert: 'px', //(String) 需要转换的单位,默认为"px"
viewportWidth: 320,
//(Number) 设计稿的视口宽度
unitPrecision: 5, //(Number) 单位转换后保留的精度
propList: ['*'], //(Array) 能转化为vw的属性列表
viewportUnit: 'vw', //(String) 希望使用的视口单位
fontViewportUnit: 'vw', //(String) 字体使用的视口单位
selectorBlackList: [], // (Array) 需要忽略的CSS选择器,不会转为视口单位,使用原有的px等单位。
minPixelValue: 1,
mediaQuery: false,
replace: true, //(Boolean)是否直接更换属性值,而不添加备用属性
exclude: undefined, //(Array or Regexp) 忽略某些文件夹下的文件或特定文件,例如 'node_modules' 下的文件
include: undefined, //(Array or Regexp) 如果设置了include,那将只有匹配到的文件才会被转换,例如只转换 'src/mobile' 下的文件 (include: /\\/src\\/mobile\\//)
landscape: false,
landscapeUnit: 'vw',
landscapeWidth: 568
示例
/* example input: */
.class
/* px-to-viewport-ignore-next */
width: 10px;
padding: 10px;
height: 10px; /* px-to-viewport-ignore */
border: solid 2px #000; /* px-to-viewport-ignore */
/* example output: */
.class
width: 10px;
padding: 3.125vw;
height: 10px;
border: solid 2px #000;
使用PostCss配置文件时,在postcss.config.js
添加如下配置
module.exports =
plugins:
// ...
'postcss-px-to-viewport':
// options
方案三:可视化图形可以使用DataV
根据固定的比例开发,界面显示用100%的开发方式,内部字体和尺寸都可以函数方法适配,其实就是另一种方式的transform适配方案
// 使用标签
<dv-full-screen-container>
...插入内容
<div></div>
</dv-full-screen-container>
方案四:采用amfe-flexible
结合postcss
插件(postcss-pxtorem):
在postcss.config.js
添加如下配置
module.exports =
plugins:
// ...
'postcss-pxtorem':
rootValue: 192, //PC端(1920的UI图)——换算基数(分辨率÷10)
propList: ['*'],
unitPrecision: 5, //保留rem小数点多少位
exclude: /(node_module)/ //默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
selectorBlackList: ['.el-'], //要忽略并保留为px的选择器
replace: false, // (布尔值)替换包含REM的规则,而不是添加回退。
mediaQuery: false, //媒体查询( @media screen 之类的)中不生效
minPixelValue: 12, //px小于12的不会被转换
,
如果个别属性不想px转化rem,可以写成14Px
或者14PX
的单位
// 安装amfe-flexible
npm install amfe-flexible -S
# 主要作用是设置更目录fontsize大小 rem才会有基数计算
或者也可以手动写utilRem.js
// 动态获取实际文档宽高并设置body缩放系数
// 基准大小
const baseSize = 14
// 设置 rem 函数
function setRem ()
// 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。
const scale = document.documentElement.clientWidth / 1920
// 设置页面根节点字体大小
document.documentElement.style.fontSize = (baseSize * Math.min(scale, 2)) + 'px'
// 初始化
setRem()
// 改变窗口大小时重新设置 rem
window.onresize = function ()
setRem()
vue项目数据大屏自适应解决方案
参考技术A 描述公司项目需要做数据大屏,自己连夜薅头发搜索查询出。目前可满足需求的方案。
可使用适用于多分辨率,移动端亦可使用
以下方法Vue3 + vite 亦可使用
安装依赖
amfe-flexible 是一个自动计算并在项目中html,body标签中添加基础font-size(用过rem单位的同学应该都知道这个是多么的重要)
postcss-px-to-viewport-8-plugin 是为了可自动将px单位转换为vw单位,避免数学不好的同学将设计稿转换单位(不喜欢vw单位的同学之后我会介绍转换r如何转换rem)
项目配置
1 在main.js中引入 amfe-flexible
2 在根目录下(也就是package.json文件同级)创建postcss.config.js文件, 配置如下
注:
如想转换rem单位亦可引入postcss-pxtorem
并于postcss.config.js文件中做如下配置
如果不想引入amfe-flexible或引入报错亦可使用以下方法实现同种效果:
新建utils/flexible.js文件
以上是关于可视化大屏自适应方案的主要内容,如果未能解决你的问题,请参考以下文章