大屏自适应容器组件-Vue3+TS
1.引言
在做数字大屏时,图表能跟着浏览器的尺寸自动变化,本文采用Vue3前端框架,采用TypeScript语言,封装了一个大屏自适应组件,将需要显示的图表放入组件的插槽中,就能实现自适应屏幕大小的效果。
2.实际效果

3.组件代码
/** * @ScaleScreen.vue * @author: zgr * @createTime: 2023/9/22 */<template><div class="screen-wrapper" ref="screenWrapper" :style="wrapperStyle"><slot></slot></div>
</template><script lang="ts" setup>
import { CSSProperties, PropType } from 'vue'
import { useFullscreen } from '@vueuse/core'
const { toggle } = useFullscreen()defineOptions({ name: 'ScaleScreen' })
interface IState {originalWidth: string | numberoriginalHeight: string | numberwidth?: string | numberheight?: string | numberobserver: null | MutationObserver
}
type IAutoScale =| boolean| {x?: booleany?: boolean}const props = defineProps({width: {type: [String, Number] as PropType<string | number>,default: 1920},height: {type: [String, Number] as PropType<string | number>,default: 1080},fullScreen: {type: Boolean as PropType<boolean>,default: false},autoScale: {type: [Object, Boolean] as PropType<IAutoScale>,default: true},delay: {type: Number as PropType<number>,default: 500},boxStyle: {type: Object as PropType<CSSProperties>,default: () => ({})},wrapperStyle: {type: Object as PropType<CSSProperties>,default: () => ({})},bodyOverflowHidden: {type: Boolean as PropType<boolean>,default: true}
})const state = reactive<IState>({currentWidth: 0,currentHeight: 0,originalWidth: 0,originalHeight: 0,observer: null
})
//ref
const screenWrapper = ref<HTMLElement>()//全屏函数
const toggleFullscreen = () => {toggle()
}
//按键F11全屏退出全屏
const KeyDown = (event: KeyboardEvent) => {if (event.code == 'F9') {toggleFullscreen()}
}const listenKeyDown = () => {window.addEventListener('keydown', KeyDown, true) //监听按键事件
}
const removeListenKeyDown = () => {window.removeEventListener('keydown', KeyDown, false) //监听按键事件
}let bodyOverflowHiddenStr: string
/*** 防抖函数* @param {Function} fn* @param {number} delay* @returns {() => void}*/
const debounce = (fn: Function, delay: number) => {let timer: NodeJS.Timeoutreturn function (...args: any[]): void {if (timer) {clearTimeout(timer)}timer = setTimeout(() => {typeof fn === 'function' && fn.apply(null, args)clearTimeout(timer)},delay > 0 ? delay : 100)}
}
const initBodyStyle = () => {if (props.bodyOverflowHidden) {bodyOverflowHiddenStr = document.body.style.overflowdocument.body.style.overflow = 'hidden'}
}
const initSize = () => {return new Promise((resolve) => {// console.log("初始化样式");nextTick(() => {// region 获取大屏真实尺寸if (props.width && props.height) {state.currentWidth = props.widthstate.currentHeight = props.height} else {state.currentWidth = screenWrapper.value?.clientWidthstate.currentHeight = screenWrapper.value?.clientHeight}// endregion// region 获取画布尺寸if (!state.originalHeight || !state.originalWidth) {state.originalWidth = window.screen.widthstate.originalHeight = window.screen.height}// endregionresolve()})})
}
const updateSize = () => {if (state.width && state.height) {screenWrapper.value!.style.width = `${state.width}px`screenWrapper.value!.style.height = `${state.height}px`} else {screenWrapper.value!.style.width = `${state.originalWidth}px`screenWrapper.value!.style.height = `${state.originalHeight}px`}
}
const autoScale = (scale: number) => {if (!props.autoScale) returnconst domWidth = screenWrapper.value!.clientWidthconst domHeight = screenWrapper.value!.clientHeightconst currentWidth = document.body.clientWidthconst currentHeight = document.body.clientHeightscreenWrapper.value!.style.transform = `scale(${scale},${scale})`let mx = Math.max((currentWidth - domWidth * scale) / 2, 0)let my = Math.max((currentHeight - domHeight * scale) / 2, 0)if (typeof props.autoScale === 'object') {!props.autoScale.x && (mx = 0)!props.autoScale.y && (my = 0)}screenWrapper.value!.style.margin = `${my}px ${mx}px`
}
const updateScale = () => {// 获取真实视口尺寸const currentWidth = document.body.clientWidthconst currentHeight = document.body.clientHeight// 获取大屏最终的宽高const realWidth = state.width || state.originalWidthconst realHeight = state.height || state.originalHeight// 计算缩放比例const widthScale = currentWidth / +realWidthconst heightScale = currentHeight / +realHeight// 若要铺满全屏,则按照各自比例缩放if (props.fullScreen) {screenWrapper.value!.style.transform = `scale(${widthScale},${heightScale})`return false}// 按照宽高最小比例进行缩放const scale = Math.min(widthScale, heightScale)autoScale(scale)
}const onResize = debounce(async () => {await initSize()updateSize()updateScale()
}, props.delay)const initMutationObserver = () => {const observer = (state.observer = new MutationObserver(() => {onResize()}))observer.observe(screenWrapper.value!, {attributes: true,attributeFilter: ['style'],attributeOldValue: true})
}
//设置数字大屏背景颜色为黑色
const setBgColor = () => {document.getElementsByTagName('body')[0].setAttribute('style', 'background: black')
}onMounted(() => {setBgColor()initBodyStyle()nextTick(async () => {await initSize()updateSize()updateScale()window.addEventListener('resize', onResize)initMutationObserver()})listenKeyDown()
})onBeforeUnmount(() => {window.removeEventListener('resize', onResize)removeListenKeyDown()state.observer?.disconnect()if (props.bodyOverflowHidden) {document.body.style.overflow = bodyOverflowHiddenStr}
})
</script><style scoped lang="scss">
.screen-wrapper {transition-property: all;transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);transition-duration: 500ms;position: relative;overflow: hidden;z-index: 100;transform-origin: left top;
}
</style>
4.感谢
1.GitHub - Alfred-Skyblue/v-scale-screen: Vue large screen adaptive component vue大屏自适应组件
2.koi-screen-plus: vue3版本数据大屏模板
3.DataV - Vue3 | DataV - Vue3
相关文章:
大屏自适应容器组件-Vue3+TS
1.引言 在做数字大屏时,图表能跟着浏览器的尺寸自动变化,本文采用Vue3前端框架,采用TypeScript语言,封装了一个大屏自适应组件,将需要显示的图表放入组件的插槽中,就能实现自适应屏幕大小的效果。 2.实际…...
java图书信息管理
一、项目概述 本图书信息管理系统旨在提供一个直观的用户界面,用于管理图书馆或书店的图书信息。系统包括图书添加、查询、借阅和归还等功能。 二、系统架构 系统采用JavaSwing作为前端UI框架,后端使用Java Servlet处理业务逻辑,数据存储在…...
apache服务器出现No input file specified.解决方案
APACHE服务器出现No input file specified.解决方案 thinkcmf程序默认的.htaccess里面的规则: <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php/$1 [QSA…...
你写过的最蠢的代码是?——全栈开发篇
🌷🍁 博主猫头虎 带您 Go to New World.✨🍁 🦄 博客首页——猫头虎的博客🎐 🐳《面试题大全专栏》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 &a…...
正点原子嵌入式linux驱动开发——TF-A初探
上一篇笔记中,正点原子的文档简单讲解了一下什么是TF-A,并且也学习了如何编译TF-A。但是TF-A是如何运行的,它的一个运行流程并未涉及。TF-A的详细运行过程是很复杂的,涉及到很多ARM处理器底层知识,所以这一篇笔记的内容…...
【网安别学成开发】之——python篇
经典入门编程题 1.猜数字 经典的猜数字游戏,几乎所有人学编程时都会做。 功能描述: 随机选择一个三位以内的数字作为答案。用户输入一个数字,程序会提示大了或是小了,直到用户猜中。 #!/usr/bin/env python3import randomresu…...
vue图片显示
一、Vue图片显示方法: 1.直接使用<img>标签: 最简单的方法是使用<img>标签,并将图片的URL作为src属性的值。例如: <img src"path/to/your/image.jpg" alt"Image"> 如果是绝对路径&#x…...
S32K144 GPIO编程
前面的文章介绍了如何在MDK-Keil下面进行S32K144的开发,下面就使用该工程模板进行GPIO LED的编程试验。 1. 开发环境 S32K144EVB-Q100开发板MDK-Keil Jlink 2. 硬件连接 S32K144EVB-Q100开发板关于LED的原理图如下: 也就是具体连接关系如下…...
域名备案流程(个人备案,腾讯云 / 阿里云)
文章目录 1.网站备案的目的2.备案准备的材料2.1 网站域名2.2 云资源或备案授权码2.3 电子材料 3.首次个人备案准备的材料3.1 主体相关3.2 域名相关3.3 网站相关3.4 网站服务相关3.5 变更相关 4.个人备案流程4.1 登录系统4.2 填写备案信息🍀 填写备案省份ἴ…...
子网ip和子网掩码的关系
子网ip和子网掩码的关系 一个IP地址被分为两部分:网络地址和主机地址。这是通过子网掩码来实现的。 子网掩码(Subnet Mask)是一个32位的二进制数,它用来区分一个IP地址中的网络地址和主机地址。在子网掩码中,网络地址…...
openGauss学习笔记-88 openGauss 数据库管理-内存优化表MOT管理-内存表特性-使用MOT-MOT使用将磁盘表转换为MOT
文章目录 openGauss学习笔记-88 openGauss 数据库管理-内存优化表MOT管理-内存表特性-使用MOT-MOT使用将磁盘表转换为MOT88.1 前置条件检查88.2 转换88.3 转换示例 openGauss学习笔记-88 openGauss 数据库管理-内存优化表MOT管理-内存表特性-使用MOT-MOT使用将磁盘表转换为MOT …...
网络-Ajax
文章目录 前言一、Ajax优点:缺点: 二、使用步骤XNLHttpRequest对象完整代码 总结 前言 本文主要记录Ajax技术的简介,以及用法。 一、Ajax Ajax是一组用于在Web浏览器和Web服务器之间进行异步通信的Web开发技术。 它代表着Asynchronous Java…...
Autowired和Resource的关系
相同点对于下面的代码来说,如果是Spring容器的话,两个注解的功能基本是等价的,他们都可以将bean注入到对应的field中 不同点但是请注意,这里说的是基本相同,说明还是有一些不同点的: byName和byType匹配顺…...
HashTable, HashMap, ConcurrentHashMap 之间的区别
HashMap: 线程不安全. key 允许为 null。 Hashtable: 线程安全. 使用 synchronized 锁 Hashtable 对象, 效率较低. key 不允许为 null.。只是简单的把关键方法上加上了 synchronized 关键字。如 get 和 set ,这相当于直接针对 Hashtable 对象本身加锁,如…...
Maven下载源码出现:Cannot download sources Sources not found for org.springframwork...
Maven下载源码出现:Cannot download sources Sources not found for org.springframwork… 最近重装了IDEA再次查看源码时发现总是报错,网上找了很多,发现解决方法都是在项目终端执行如下命令: mvn dependency:resolve -Dclassi…...
C进阶--字符函数和字符串函数介绍
✨ 更多细节参考 cplusplus.com/reference/cstring/ 使用方式: ⭕ 求字符串长度 🖌 strlen 函数原型: size_t strlen ( const char * str ); 作用: 获取字符串长度 ✨补充: ⭐字符串以 \0 作为结束标志&…...
算法通关村第五关-二叉树遍历(层数优先)之经典问题:简单的层序遍历、层序遍历分层、自底向上的层序遍历
基础知识(青铜挑战) 了解二叉树的基础知识 实战训练(白银挑战) 简单的层序遍历 基本的层序遍历思路很清晰: 给你一个二叉树根节点,你需要创建一个队列 queue 来遍历节点,一个链表 list 来存储…...
C++左右值及引用
1 左值和右值 简单记法:能取地址的是左值,不能取地址的是右值 右值一般是常量 例: i 是右值,因为先把 i 赋值给临时变量,临时变量在1,而临时变量是将亡值,&i取地址会报错 i是左值…...
如何备份和恢复数据库
目录 1.xtrabackup 是什么2.全量备份3.增量备份4.使用备份进行恢复5.原理6.参考 本文主要介绍如何使用xtrabackup 进行数据库的备份和恢复,并在最后介绍了原理。 1.xtrabackup 是什么 XtraBackup是由Percona开发的一款开源的MySQL数据库备份工具。它可以对InnoDB和…...
简化数据库操作:探索 Gorm 的约定优于配置原则
文章目录 使用 ID 作为主键数据库表名TableName临时指定表名列名时间戳自动填充CreatedAtUpdatedAt时间戳类型Gorm 采用约定优于配置的原则,提供了一些默认的命名规则和行为,简化开发者的操作。 使用 ID 作为主键 默认情况下,GORM 会使用 ID 作为表的主键: type User st…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
