可视化指挥调度平台软件,大屏WEB软件系统

发布时间: 2024-05-29 20:25:30

响应式方案

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) => {
      // 视频流返回的内容
    })
  }
}

再也不用忍受事件回调的苦难了!