大屏自适应容器组件-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…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...
leetcode73-矩阵置零
leetcode 73 思路 记录 0 元素的位置:遍历整个矩阵,找出所有值为 0 的元素,并将它们的坐标记录在数组zeroPosition中置零操作:遍历记录的所有 0 元素位置,将每个位置对应的行和列的所有元素置为 0 具体步骤 初始化…...
门静脉高压——表现
一、门静脉高压表现 00:01 1. 门静脉构成 00:13 组成结构:由肠系膜上静脉和脾静脉汇合构成,是肝脏血液供应的主要来源。淤血后果:门静脉淤血会同时导致脾静脉和肠系膜上静脉淤血,引发后续系列症状。 2. 脾大和脾功能亢进 00:46 …...
