可视化指挥调度平台软件,大屏WEB软件系统
响应式方案
rem
上次已经说了2个响应式方案,都是基于缩放去做的,今天我们来讲下rem方案。
rem原理:rem单位是基于HTML元素的font-size来计算的,这意味着所有使用rem单位的元素的大小都是相对于根元素(即HTML元素)的字体大小来确定的。AIoT万物智联,智能安全帽生产厂家,执法记录仪生产厂家,智能安全帽、智能头盔、头盔记录仪、执法记录仪、智能视频分析/边缘计算AI盒子、车载DVR/NVR、布控球、室外高精度定位RTK/室内高精度定位UWB/蓝牙信标定位、智能眼镜、智能手电、无人机4G/5G补传系统,多源视频融合~融合通信~安全生产管控平台~大型可视指挥调度平台VMS/smarteye 。
举个栗子:
<html style="fontSize: 16px">
<head>
<style>
.box {
width: 2rem;
}
</style>
</head>
<body>
<div class='box'>文字</div>
</body>
</html>
此时html的fontSize=16px,box元素的宽度是2rem单位;也就是说,如果1rem = 16px的话,此时box的渲染宽度应该是2*16=32px。
那么如果浏览器大小发生变化,此时html的fontSize也会动态改变。例如浏览器变大,html的fontsize=20px了,那此时box的宽度就会动态变更成20*2=40px;
所以说页面内的所有元素我们都使用rem作为单位,然后只需要监听屏幕的缩放,动态去修改html的fontsize即可实现响应式。
Ok,原理明白了,我们接下来直接封装一个基于rem方案的响应式hooks,方便在vue3的项目里使用,注释我已经写的很清楚了。
/*
* @Description: rem响应式方案hooks
*/
import { shallowReadonly, ref } from 'vue'
const flexiableRatio = ref(1)
const SCREEN_WIDTH = 1440 // 设定的浏览器的基准宽度
/**
* 启用自适应
* @param window
* @param document
*/
export const useFlexible = (window, document) => {
const docEl = document.documentElement // 返回文档的root元素
const dpr = window.devicePixelRatio || 1 // 获取设备的dpr,即当前设置下物理像素与虚拟像素的比值
/**
* 设置默认字体大小,默认的字体大小继承自body
*/
function setBodyFontSize() {
if (document.body) {
document.body.style.fontSize = 12 * dpr + 'px'
} else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}
setBodyFontSize()
/**
* 更新分辨率尺寸
*/
function updateScreenSize() {
const rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
flexiableRatio.value = docEl.clientWidth / SCREEN_WIDTH
}
updateScreenSize()
// reset rem unit on page resize
window.addEventListener('resize', updateScreenSize)
window.addEventListener('pageshow', function (e) {
if (e.persisted) {
updateScreenSize()
}
})
return {
flexiableRatio: shallowReadonly(flexiableRatio)
}
}
如何使用?直接在应用的入口文件,例如main.js中调用
import { createApp } from 'vue'
import App from './App.vue'
import { useFlexible } from '@/hooks/useFlexible'
// 创建并挂载根实例
const app = createApp(App)
// 响应式
useFlexible(window, document)
app.mount('#app')
事件监听辅助
eventemmiter
eventemmiter是一个轻量级的高性能的事件发布/订阅库,强推!它主要有以下优势:
-
事件发布/订阅:允许对象在内部发生某些事件时通知其他对象,这些对象可以订阅这些事件并响应它们。
-
解耦:它帮助实现发布者和订阅者之间的解耦,发布者不需要知道谁在监听事件,订阅者也不需要知道事件是如何产生的。
-
异步事件处理:EventEmitter3 支持异步事件处理,可以提高性能,尤其是在高并发场景下。
-
性能优化:相比于 Node.js 内置的 EventEmitter,EventEmitter3 进行了性能优化,尤其是在处理大量事件监听器时。
在做大屏开发的时候,经常会用到一些二维或者三维的框架,这些框架部分API经常会有事件回调onEvent,回调是非常难用的,特别遇到跨组件或者跨类通信的时候,更是鸡肋。
但是有了eventemmiter,就方便了很多。
安装:
npm i eventemitter3
二次封装一个EventEmit类,当然你也可以直接用,根据个人需求,我这里是兼容做了Promise的处理:
import { EventEmitter } from 'eventemitter3';
/**
* 事件监听触发类
*/
export default class EventEmit {
#ee: EventEmitter; // eventEmitter实例
constructor() {
this.#ee = new EventEmitter();
}
/**
* 一次性事件监听
* @param eventName 事件名称
* @param fn 事件回调
* @returns Promise
*/
once(eventName: string, fn?: (...args: any[]) => void): Promise<unknown> {
if (fn) {
this.#ee.once(eventName, fn);
} else {
return new Promise((resolve) => {
return this.#ee.once(eventName, resolve);
});
}
}
/**
* 事件监听
* @param eventName 事件名称
* @param fn 事件回调
* @returns Promise
*/
on(eventName: string, fn?: (...args: any[]) => void): Promise<unknown> {
if (fn) {
this.#ee.on(eventName, fn);
} else {
return new Promise((resolve) => {
return this.#ee.on(eventName, resolve);
});
}
}
/**
* 移除事件监听
* @param eventName 事件名称
*/
removeListener(eventName: string) {
this.#ee.removeListener(eventName);
}
/**
* 事件触发
* @param eventName 事件名称,与on事件名称保持一致
* @param args 需要传递给on的参数
*/
emit(eventName: string, args?: any) {
this.#ee.emit(eventName, args);
}
}
在A类中做监听:
import EventEmit from './EventEmitter';
export const ee = new EventEmit();
export class A {
/**UE视频流实例 */
stream: any;
constructor(stream: any) {
this.stream = stream;
// 监听视频流返回的事件回调
this.stream.addResponseEventListener('handle_responses', this.#getUeRes);
}
/**
* UE返回的数据
* @param res 返回的数据
* @returns
*/
#getUeRes(res: any): void {
ee.emit('getUeResponse', res);
}
}
在B类中监听视频流返回的事件回调:
import { ee } from '../Base/Base';
export class B {
doSomeThing() {
// do some thing...
// 需要监听视频流的回调,此时就方便很多了
ee.on("getUeResponse", (e) => {
// 视频流返回的内容
})
}
}
再也不用忍受事件回调的苦难了!
