位置: IT常识 - 正文

可视化大屏的几种屏幕适配方案,总有一种是你需要的(可视化大屏的几种模式)

编辑:rootadmin
可视化大屏的几种屏幕适配方案,总有一种是你需要的

推荐整理分享可视化大屏的几种屏幕适配方案,总有一种是你需要的(可视化大屏的几种模式),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:可视化大屏介绍,可视化大屏设计是什么,可视化大屏效果图,可视化大屏的功能,可视化大屏 ui,可视化大屏幕,可视化大屏的功能,可视化大屏的几种模式,内容如对您有帮助,希望把文章链接给更多的朋友!

假设我们正在开发一个可视化拖拽的搭建平台,可以拖拽生成工作台或可视化大屏,或者直接就是开发一个大屏,首先必须要考虑的一个问题就是页面如何适应屏幕,因为我们在搭建或开发时一般都会基于一个固定的宽高,但是实际的屏幕可能大小不一,接下来我们就尝试几种简单且常见的方案,并简单分析一下利弊。

demo

首先写个基础的demo给后续使用:

<script setup>import { ref } from "vue";import Widget from "./components/Widget.vue";import LineChart from "./components/LineChart.vue";import BarChart from "./components/BarChart.vue";import PieChart from "./components/PieChart.vue";import FunnelChart from "./components/FunnelChart.vue";// 画布宽高const canvasWidth = ref(1920);const canvasHeight = ref(1080);// 组件宽高const widgetWidth = ref(960);const widgetHeight = ref(540);</script><template> <div class="canvasBox"> <div class="canvas" :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }" > <Widget :width="widgetWidth" :height="widgetHeight" :left="0" :top="0"> <LineChart></LineChart> </Widget> <Widget :width="widgetWidth" :height="widgetHeight" :left="widgetWidth" :top="0"> <BarChart></BarChart> </Widget> <Widget :width="widgetWidth" :height="widgetHeight" :left="0" :top="widgetHeight"> <PieChart></PieChart> </Widget> <Widget :width="widgetWidth" :height="widgetHeight" :left="widgetWidth" :top="widgetHeight"> <FunnelChart></FunnelChart> </Widget> </div> </div></template><style scoped>.canvasBox { width: 100vw; height: 100vh;}.canvas { position: relative;}</style>

每个图表组件的宽高都设为100%,然后都被Widget组件包裹,所以实际宽高是依赖Widget组件的,Widget组件为绝对定位,并且宽高、位置通过props传入,模拟我们的拖拽操作,简单起见,所有图表的宽高我们都设为了相同的。

Widget组件:

<script setup>const props = defineProps({ width: { type: Number, default: 0, }, height: { type: Number, default: 0, }, left: { type: Number, default: 0, }, top: { type: Number, default: 0, },});</script><template> <div class="widgetBox" :style="{ width: width + 'px', height: height + 'px', left: left + 'px', top: top + 'px', }" > <slot></slot> </div></template><style scoped>.widgetBox { position: absolute;}</style>

组件整体的容器为类名为canvas的元素,相对定位,宽高也是动态设置的,canvas元素的父级canvasBox元素宽高设为和屏幕宽高一致。

固定尺寸

即宽度、高度固定,如果宽高小于屏幕宽高则在屏幕居中。

这个是最简单的方案了,相当于不适配屏幕,画布配置了多大实际就是多大,不随屏幕的变化而变化,所以各个组件的宽高也是在配置后不会改变,一般用于尺寸固定且后期不会改变的可视化大屏。

我们前面的demo初始就是这种方式:

当然,如果宽高小于屏幕的话居中的逻辑需要加一下,居中的方法有很多,通过css、js都可,根据自己的喜好来就行:

// 画布的位置const canvasLeft = ref(0);const canvasTop = ref(0);// 如果屏幕的宽或高比画布的大,那么居中显示let windowWidth = window.innerWidth;let windowHeight = window.innerHeight;if (windowWidth > canvasWidth.value) { canvasLeft.value = (windowWidth - canvasWidth.value) / 2;}if (windowHeight > canvasHeight.value) { canvasTop.value = (windowHeight - canvasHeight.value) / 2;}<div class="canvas" :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px', left: canvasLeft + 'px', top: canvasTop + 'px', }" ></div>

判断窗口宽度和高度是否大于画布的宽高,是的话通过left或top来调整:

自适应宽度

即宽度适应屏幕,高度不变,这种方案的缺点是垂直方向上会出现滚动条。

比如画布设置的宽度为1920,但是实际上屏幕的宽度为1280,那么缩小了1.5倍,那么画布和每个组件的宽度也需要同步缩小1.5倍,并且每个组件的left值也需要进行动态调整。

首先实现一下容器元素canvas的尺寸调整:

// 保存原始画布的宽度const originCanvasWidth = ref(canvasWidth.value);// 宽度缩放比例const ratioWidth = ref(1);// 当前窗口的宽度let windowWidth = window.innerWidth;// 将画布宽度设置为当前窗口的宽度canvasWidth.value = windowWidth;// 计算当前宽度和原始宽度的比例ratioWidth.value = windowWidth / originCanvasWidth.value;

然后再把这个比例传给Widget组件进行调整:

<Widget :ratioWidth="ratioWidth"> <LineChart></LineChart></Widget><Widget :ratioWidth="ratioWidth"> <BarChart></BarChart></Widget><Widget :ratioWidth="ratioWidth"> <PieChart></PieChart></Widget><Widget :ratioWidth="ratioWidth"> <FunnelChart></FunnelChart></Widget>

在Widget组件里我们只要把宽度和left都乘以这个比例即可,为什么是乘,很简单:

newWidth / width = ratioWidth = windowWidth / originCanvasWidthnewWidth = width * ratioWidth// left同样看做是一个距左侧的宽度即可<div class="widgetBox" :style="{ width: width * ratioWidth + 'px', height: height + 'px', left: left * ratioWidth + 'px', top: top + 'px', }" > <slot></slot></div>

自适应屏幕

即宽高都自适应,和上一种方案相比,这种横竖都不会出现滚动条,且能完全铺满屏幕。

实现也很简单,在上一个【自适应宽度】的基础上加上高度自适应即可。

// 画布原始宽高const originCanvasWidth = ref(canvasWidth.value);const originCanvasHeight = ref(canvasHeight.value);// 缩放比例const ratioWidth = ref(1);const ratioHeight = ref(1);// 当前窗口的宽高let windowWidth = window.innerWidth;let windowHeight = window.innerHeight;// 将画布宽高设置为当前窗口的宽高canvasWidth.value = windowWidth;canvasHeight.value = windowHeight;// 计算当前宽高和原始宽高的比例ratioWidth.value = windowWidth / originCanvasWidth.value;ratioHeight.value = windowHeight / originCanvasHeight.value;

同样再把比例传给Widget组件进行调整:

<Widget :ratioWidth="ratioWidth" :ratioHeight="ratioHeight"> <LineChart></LineChart></Widget><Widget :ratioWidth="ratioWidth" :ratioHeight="ratioHeight"> <BarChart></BarChart></Widget><Widget :ratioWidth="ratioWidth" :ratioHeight="ratioHeight"> <PieChart></PieChart></Widget><Widget :ratioWidth="ratioWidth" :ratioHeight="ratioHeight"> <FunnelChart></FunnelChart></Widget><div class="widgetBox" :style="{ width: width * ratioWidth + 'px', height: height * ratioHeight + 'px', left: left * ratioWidth + 'px', top: top * ratioHeight + 'px', }" > <slot></slot></div>

整体等比例缩放可视化大屏的几种屏幕适配方案,总有一种是你需要的(可视化大屏的几种模式)

即通过css的transform属性来对组件容器canvas进行整体的缩放,保持原比例,在屏幕居中显示,当然你可以选择只缩放宽度或高度,但是这样会变形。

前面的两种方案,我们的组件开发时都必须要考虑容器的宽高,即需要进行适配,但是宽高比太极限了说实话很难处理,显示效果肯定是比较差的,但是这种整体等比例适配就无需考虑这种情况。

实际项目中如果有大屏需要适应屏幕,我一般都通过这种方法,优点是简单,缺点是水平或垂直空间上可能会留白,但是背景是全屏的,所以效果也不会很差。

实现也很简单,计算一下画布原始比例,再计算一下屏幕的比例,然后再判断是宽度和屏幕一致,高度自适应,还是高度和屏幕一致,宽度自适应:

// 当前窗口宽高比例let windowWidth = window.innerWidth;let windowHeight = window.innerHeight;let windowRatio = windowWidth / windowHeight;// 画布原始宽高比例const canvasRatio = canvasWidth.value / canvasHeight.value;// 计算画布适应后的新宽高let newCanvasWidth = 0;let newCanvasHeight = 0;if (canvasRatio > windowRatio) {// 画布的宽高比大于屏幕的宽高比 // 画布的宽度调整为屏幕的宽度 newCanvasWidth = windowWidth; // 画布的高度根据画布原比例进行缩放 newCanvasHeight = windowWidth / canvasRatio;} else {// 画布的宽高比小于屏幕的宽高比 // 画布的高度调整为屏幕的高度 newCanvasHeight = windowHeight; // 画布的宽度根据画布原比例进行缩放 newCanvasWidth = windowHeight * canvasRatio;}// ...

假设屏幕的宽高相同,那么比例为1。

第一种情况,假设画布的宽是高的两倍,那么比例为2,要保持原比例2适应屏幕,显然只能宽度和屏幕一致,高度自适应,因为如果高度和屏幕一致,那么宽度需要是高度的两倍,屏幕显然显示不下:

第二种情况,假设画布的高是宽的两倍,那么比例为0.5,要保持比例为0.5适应屏幕,需要高度和屏幕一致,宽度自适应:

计算完了画布适应屏幕后的新宽高,接下来就可以计算它相对于画布原始宽高的缩放比例:

// ...// 相对于画布原始宽高的缩放比例const canvasStyle = reactive({ transform: "",});const scaleX = newCanvasWidth / canvasWidth.value;const scaleY = newCanvasHeight / canvasHeight.value;canvasStyle.transform = `scale(${scaleX}, ${scaleY})`

把样式添加到容器元素canvas上即可:

<div class="canvas" :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px', ...canvasStyle }" ></div>

显示的位置似乎有点问题,这其实是因为默认情况下元素的变换都是以自身的中心点为原点进行变换的:

我们只要改成以左上角为原点即可:

const canvasStyle = reactive({ transform: "", transformOrigin: `left top`// 改成以左上角为变换原点});

最后再来让它居中:

// 居中const translateX = (windowWidth - newCanvasWidth) / 2 / scaleX;const translateY = (windowHeight - newCanvasHeight) / 2 / scaleY;canvasStyle.transform = `scale(${scaleX}, ${scaleY}) translate(${translateX}px, ${translateY}px)`;

窗口的宽高减去画布适应后的新宽高,即剩余的空间,再除以2进行居中显示,为什么还要除以缩放值呢,因为translate的值也会随scale进行缩放,比如translateX计算出来为100,scaleX为0.5,那么实际上最终的偏移量为100*0.5=50,这显然不对,所以我们除一个缩放值进行抵消。

这个方案似乎很完美,那么还有没有问题呢,显然是有的,一个小问题是缩放后文字可能会模糊,这个问题不大,笔者遇到的另一个问题是如果使用了getBoundingClientRect方法获取元素信息,本意是获取元素原始的尺寸数据,但是缩放后返回的就是缩放后的数据,那么可能会和我们的原始意图出现偏差,比如有一个如下的div:

<div ref="el1" style="width: 200px; height: 200px; background: red; position: absolute; left: 50px; top: 50px;"></div>

我们想要动态根据这个div大小和位置复制一个div:

<div ref="el2" style="background: green; position: absolute"></div>const { width, height } = el1.value.getBoundingClientRect();const { left, top } = window.getComputedStyle(el1.value);el2.value.style.width = `${width}px`;el2.value.style.height = `${height}px`;el2.value.style.left = left;el2.value.style.top = top;

可以看到获取到的宽高比实际的小了一点,这显然不是我们需要的,解决方法是要么不要使用getBoundingClientRect方法,使用offsetWdith等不会被缩放影响的方法或属性获取元素尺寸,要么把获取到的数据除以缩放值。

当然可能还会存在其他一些属性或方法也会存在这个问题,这就需要各位在实际的开发时进行测试了。

总结

本文简单总结了一下大屏适配的几种方法,没有哪一种是最好的,也没有哪一种是非常完美的,没办法,很多时候都是需要进行一定妥协的。

demo地址:https://wanglin2.github.io/visual-drag-platform-fit-demo/

demo仓库地址:https://github.com/wanglin2/visual-drag-platform-fit-demo

本文链接地址:https://www.jiuchutong.com/zhishi/292301.html 转载请保留说明!

上一篇:琥珀山国家公园里的豹变色龙,马达加斯加 (© Christian Ziegler/Minden Pictures)(琥珀山庄位于我国哪个省)

下一篇:曲折的tensorflow安装过程(Tensorflow 安装问题的解决)(曲折的拼音)

  • 朋友圈营销中的七大核心错误 你中枪了吗(朋友圈营销的目的)

    朋友圈营销中的七大核心错误 你中枪了吗(朋友圈营销的目的)

  • 华为手环7支持语音助手吗(华为手环7支持NFC吗)

    华为手环7支持语音助手吗(华为手环7支持NFC吗)

  • 微信红包怎么退回(微信红包怎么退回给自己)

    微信红包怎么退回(微信红包怎么退回给自己)

  • xs手机突然无法上滑(苹果xs无法激活什么情况)

    xs手机突然无法上滑(苹果xs无法激活什么情况)

  • 抖音直播的本场点赞是什么(抖音直播的本场怎么设置)

    抖音直播的本场点赞是什么(抖音直播的本场怎么设置)

  • 腾讯课堂退出去老师能看见吗(腾讯课堂退出去再进会算时长吗)

    腾讯课堂退出去老师能看见吗(腾讯课堂退出去再进会算时长吗)

  • pd和qc充电区别(qc和pd快充互相兼容吗)

    pd和qc充电区别(qc和pd快充互相兼容吗)

  • 华为充电一会充一会停(华为充电一会充一会不充是什么情况)

    华为充电一会充一会停(华为充电一会充一会不充是什么情况)

  • oppo怎么同时开两个麦(oppo手机怎么设置双开)

    oppo怎么同时开两个麦(oppo手机怎么设置双开)

  • 淘宝开卡领红包是什么意思(淘宝开卡领红包有风险吗)

    淘宝开卡领红包是什么意思(淘宝开卡领红包有风险吗)

  • word论文怎么添加目录(word论文怎么添加注释)

    word论文怎么添加目录(word论文怎么添加注释)

  • 毒上个人卖家发货什么意思(毒上卖家发货要自己掏钱吗)

    毒上个人卖家发货什么意思(毒上卖家发货要自己掏钱吗)

  • iphone闹钟会响一天吗(苹果闹钟为什么响一下声音就小了)

    iphone闹钟会响一天吗(苹果闹钟为什么响一下声音就小了)

  • 计算机软硬件包括什么(计算机软硬件包括哪些东西)

    计算机软硬件包括什么(计算机软硬件包括哪些东西)

  • ipad开机键是哪个(ipad开机键是哪一个)

    ipad开机键是哪个(ipad开机键是哪一个)

  • 小米cc9e支持18w快充吗(小米cc9e支持nfc吗)

    小米cc9e支持18w快充吗(小米cc9e支持nfc吗)

  • 网卡驱动卸载了怎么安装(网卡驱动卸载了还能上网吗)

    网卡驱动卸载了怎么安装(网卡驱动卸载了还能上网吗)

  • 怎么把pdf文件拆开(怎么把pdf文件拆分成几个小文件免费)

    怎么把pdf文件拆开(怎么把pdf文件拆分成几个小文件免费)

  • 文本框里的字怎么居中(文本框里的字怎么垂直居中)

    文本框里的字怎么居中(文本框里的字怎么垂直居中)

  • 华为不支持网易云音乐吗(华为不支持网易大神登录)

    华为不支持网易云音乐吗(华为不支持网易大神登录)

  • 红米note4耗电解决办法(红米note4耗电太厉害)

    红米note4耗电解决办法(红米note4耗电太厉害)

  • 苹果手机如何关闭LED闪烁提醒灯(苹果手机如何关手机)

    苹果手机如何关闭LED闪烁提醒灯(苹果手机如何关手机)

  • 华为手机车钥匙功能在哪里(华为手机车钥匙怎么配对)

    华为手机车钥匙功能在哪里(华为手机车钥匙怎么配对)

  • 【Vue】实现当前页面刷新的四种方法(vue获取当前行)

    【Vue】实现当前页面刷新的四种方法(vue获取当前行)

  • 【vue3】关于watch与computed的用法看这个就ok(vue watcher)

    【vue3】关于watch与computed的用法看这个就ok(vue watcher)

  • java基础-集合(java集合详解以及底层实现)

    java基础-集合(java集合详解以及底层实现)

  • 二手房交易需缴纳哪些费用
  • 消费税的计税价格是什么
  • 土地使用权契税入账会计分录
  • 水利建设基金的会计分录
  • 销售费用包括啥
  • 建筑公司核定征收是什么意思
  • 个人借款给公司利息收入要交税吗
  • 先开了发票给客户,不付款怎么办
  • 调整跨期收入是否调增值税
  • 委托加工设备
  • 售楼部垃圾桶
  • 不动产权证拆迁的话有什么作用
  • 购买投资理财产品放的会计处理怎么做?
  • 注销公司房产税从哪年从哪年开始交
  • 票据遗失情况说明格式及范文
  • 专用发票与普通发票代码区别
  • 汉字防伪企业是哪家
  • 资金占用费如何开票
  • 服务费发生退回怎么处理
  • 第三方派遣劳务不续签补偿金哪边出
  • 对公账户发工资的利弊
  • 公司转账不开票备注服务费怎么入账
  • 材料发票清单
  • 企业所得税法如何确认应税收入
  • 老板垫付款做会计分录
  • synchost.exe - synchost是什么进程 有什么作用
  • 主营业务成本如何算
  • php中的类是什么
  • 货款已预付会计分录
  • 牙痛怎么办怎么治疗
  • php 赋值
  • PHP:json_last_error()的用法_JSON函数
  • 特许权使用费的增值税税率是多少
  • 注销小规模公司需要什么材料
  • 资产处置损益要写明细账吗
  • php 正则
  • 基于yolov5的目标检测实验任务
  • 融资租赁的固定资产所有权归谁
  • 增值税专用发票怎么开
  • 测试费计入什么会计科目
  • 深度学习|论文中常用的注意力模块合集(下)
  • 2023年会出什么车
  • 企业购进固定资产,在安装完工交付使用时
  • 长期借款的核算分为哪三个阶段
  • 销售不动产预征率是多少
  • 报税金额和开票统计不一致
  • PostgreSQL教程(三):表的继承和分区表详解
  • 资产报废的原因及情况说明
  • 企业报废车辆如何做账
  • 小规模纳税人纳多少税
  • 项目竣工决算审查
  • 长期股权投资采用成本法核算的,应按被投资单位
  • 汽车销售和租赁业务描述
  • 企业法人个人贷款企业承担吧?
  • 法人转移公司资产怎么办
  • 印花税票 购买
  • 过路费属于会计哪个科目
  • 企业应付账款的借方余额反映的是
  • 记账凭证可以先做贷方吗
  • 关联公司往来款怎么做账
  • 明细分类账如何填写
  • 原始凭证的基本内容
  • mysql添加外键约束的sql语句
  • bios密码忘记了取电池不管用
  • win8安装虚拟机的步骤
  • ubuntu16.04安装步骤
  • Linux中stat命令显示文件的基本使用教程
  • linux文件后缀名解释
  • 使用jquery操作dom
  • 队列remove
  • linux chmod s
  • python2.7多进程
  • jquery移动端ui框架
  • js制作网站
  • javascript 基础
  • python jsonp
  • jquery插件使用
  • 税务机关一案双查管理办法
  • 工会经费范围税率是多少
  • 海口社保一个月多少钱
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设