[数据可视化]数据⼤屏前端屏幕多分辨率适配⽅案(vue,echarts)
数据可视化⼤屏前端屏幕多分辨率适配⽅案(vue,charts)
写在前⾯:
第⼀次写博客, csdn账号注册很久了, 应该是2010年注册的, 当时我还在上⾼中, 当时还在写易语⾔的, 有些问题搞不懂的会来csdn看⼤佬是怎么解决的, 也写了些没什么⽤的⼩⼯具上传到csdn, 当然现在都在⽤git了. 很多⼈好奇, " 你为什么要学易语⾔, 垃圾语⾔ " , 当时是实在看不懂英语, 但是对编程(当时的理解就是编程)很有兴趣, ⾮常想学.
现在回想从 c语⾔ 易语⾔ vb javascript java python , ⼀路过来都在学习, 但是好像从来没有写过什么东西, 遇到过⽆数的bug, 掉了⽆数根头发, 现在⼤学毕业了, 赶上了2020年的疫情, 这次经历让我对⽣命有了新的看法, 也是时候静下⼼来写些东西, 沉淀⼀下⾃⼰的历程了! 第⼀次写博客不知道写什么, 胡乱写了这么⼀段, 留在这⾥, 反正也没有⼈看, 回头再看到⾃⼰第⼀篇博客的时候, 希望不忘初⼼!
项⽬代码链接:
⼀直在写 react 的, 新到⼀家公司, 同事都是写 vue , 改写 vue 不太习惯, 觉得还是 react ⽤起来更灵活更顺⼿⼀些. 好久没写前端了, 现在也回忆⼀下前端适配, 也回忆⼀下 vue 的写法
项⽬有⼀个数据可视化⼤屏的需求, 要展⽰⼀些数字资源的使⽤情况,⾥⾯有⼀些 echarts 的图表,使⽤量⼀般是⽤仪表盘的形式,使⽤情况是⼀段时间数据的柱状图.
这个项⽬是由我同事来写的, 他的习惯是直接按照设计稿的px像素直接写到页⾯上, 在电脑上预览的时候没有什么问题, 但是这个项⽬要部署在⼀块很⼤的⼤屏上的, 这个时候就发现了问题所在, 屏幕不适配
我也是刚来到这个公司和那个同事关系⽐较好, 我的⼯作也基本完成了, 所以我决定帮帮他. 选择⼀个合适的适配⽅案然后还需要快速的把代码完成改版, 最终我⽤java写了⼀个代码转换⼯具, ⼀键帮同事把代码转为适配
⽅案选择
1. px 转 rem
2. viewpoint
3. 媒体查询 @media
4. 计算屏幕缩放⽐ 动态设置像素值
每个⼈有不同的适配经验, 我这个同事适配经验⽐较少, 之前写⼩程序适配是⽤的 rpx , 这个类似于 rem 了.
备选⽅案1: px转rem
px 转 rem 是基于页⾯的fontSize 设置⼀个 rem 与 px 换算⽐例 ⽐如 16px=1rem , 20px=1rem 根据不同的屏幕设计不同的, 页⾯fontSize, 在移动端开发中这种⽅案⾮常常见.
html{/* 普通状态 */
font-size: 20px
}
html{/* 1.5倍分辨率 */
font-size: 30px
}
html{/* 2倍分辨率 */
font-size: 40px
}
.div-box{
width: 5rem;/* 5倍的font-size 普通状态下 = 100px */
}
但是当前的项⽬可能并不适⽤:
1. 页⾯中有其他已经开发有其他的元素有导航⽂字, 设置fontSize时会影响到页⾯中已经写好的内容
2. 页⾯中使⽤了 echarts 图表, ⾥⾯的参数没办法应⽤ rem 的⽐例
备选⽅案2: 媒体查询
媒体查询是⽐较常见的屏幕适配⽅案了, 可以根据不同的屏幕⼤⼩提供不同的样式⽅案, 媒体查询可以很好的⽀持多数的pc端⽹页布局需要了.
@media only screen and (max-width: 1000px){
.div-class{
width: 720px;
}
}
但是问题也是⽐较明显:
1. ⼤量书写媒体查询代码, ⽐较繁琐
2. 针对多种屏幕进⾏适配, 也⽆法保证完全兼容所有的屏幕
3. 也⽆法⽀持 echarts 图表中的参数进⾏适配
备选⽅案3: viewpoint 视⼝
viewpoint 基本是⽬前多数移动端开发都会使⽤的适配⽅式, 可以设置对移动端设备的的界⾯进⾏整体的缩放, 这种⽅式的适配是最佳的⽅案.但是缺点是很明显的, 只能在移动端进⾏ viewpoint 适配, 我们⽬前的数据⼤屏项⽬就没办法⽤了.
<meta name="viewport"content="target-densitydpi=high-dpi"/>
最终采⽤⽅案: 计算屏幕缩放⽐
我们的设计稿宽⾼⽐是 1920 * 960
由于这个数据可视化的项⽬是适配宽屏的, 我可以先铺满⾼然后屏幕左右可能会有空⽩, 空⽩的部分⽤背景图⽚填充就好了. 画⾯的布局像素依然使⽤设计标注的像素值然后再乘屏幕缩放⽐.
页⾯适配样例代码(vue) :
<template>
<div class="chart-container":class="chartContainer">
<div :> </div>
</div>
</template>
<script>
// 宽⾼⽐
const scale =1920/960;
// 屏幕导航⾼度
const headerHeight =47;
// 标签栏⾼度
const tabHeight =27;
// 标签栏间隔
const pageMargin =5;
// 设计稿⾼度
const designHeight =960;
// 画⾯上⽅间隔⾼度
const marginTop = headerHeight + tabHeight + pageMargin;
// 画布下⽅间隔⾼度
const marginBottom = pageMargin;
// 页⾯宽度
const clientWidth = document.body.clientWidth;
// 页⾯⾼度
const windowHeight = document.body.clientHeight;
// ⾯试⾼度去年上⽅间隔下⽅间隔
const clientHeight = windowHeight - marginTop - marginBottom;
// 画⾯⾼度
const innerHeight = clientHeight;
// 缩放⽐率
const rate = innerHeight / designHeight;
// 画⾯宽度
const centerWidth = clientHeight * scale;
// 画⾯左右侧空⽩宽度
const paddingWidth =(((clientWidth - pageMargin - pageMargin)-(clientHeight * scale))/2)
export default{
data:()=>({
chartContainer:{height:181* rate +'px',},
}),
methods:{
dataOtherEChart(eleId, label, value, itemValue, color, color1, temp3){
const _self =this;
let chartEle = _self.$echarts.ElementById(eleId));
let option ={
易语言教程2020title:{
textAlign:'center',
textStyle:{
rich:{ num:{ fontSize:25* rate,}, key:{ fontSize:15* rate,}}
},
subtextStyle:{ lineHeight:30* rate, fontSize:15* rate
}
}
};
chartEle.setOption(option,true);
},
}
}
</script>
改造前代码
有些是写在⾏内的 style
<div id="top-item1"class="chart-container">
<div id="main11" ></div>
<div id="other11" ></div>
<div id="other12" ></div>
<div id="other13" ></div>
</div>
⾼度直接使⽤了设计稿中的像素值 165px
有些是使⽤了css 样式定义的:
.
box-to-box{
height: 100px;
width: 85%;
margin-top: 49px;
margin-left: 60px;
display: flex;
}
把⾼度 间距 都设计成了设计稿⾥⾯的像素值, 他好像还不太会⽤flex 弹性盒布局, 这⾥的 display:flex 也没有⽣效echarts 参数:
let option ={
title:{
subtextStyle:{ lineHeight:30, fontSize:15}
},
}}
这⾥的参数是没有单位的也需要按缩放⽐缩放
vue 代码转换⼯具
⽤代码转换⼯具将写死的像素值乘以缩放⽐例
1.读取vue⽂件, 定义⽂件⾏链表 class的映射
fileReader =new FileReader(url);
// 读取⽂件
bufferedReader =new BufferedReader(fileReader);
// 结果⽂本
StringBuilder resultText =new StringBuilder();
/
/ ⾏链表⽤于查 class样式名称
LinkedList<String> lineList =new LinkedList<>();
// class样式映射
Map<String, Map<String, String>> classMap =new HashMap<>();
2.遍历⾏, 定义样式识别的正则表达式
// 每⾏插⼊链表头
lineList.addFirst(line);
// class样式识别正则
Matcher classMatcher = Patternpile(".*?-?.*?:.*?px.*?;").matcher(line);
// id class 绑定样式识别正则
Matcher classUseMatcher = Patternpile("(class|id)=\"([0-9a-z-])*?\"").matcher(line);
3.处理style 有px的位置乘以 rate

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。