大屏自适应容器组件-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…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
PHP 8.5 即将发布:管道操作符、强力调试
前不久,PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5!作为 PHP 语言的又一次重要迭代,PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是,借助强大的本地开发环境 ServBay&am…...
