Vue3 + Vite + TypeScript + dataV 打造可视化大屏

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

前言

网上有许多开源的可视化大屏项目但是分析之后还是想自己从 0 搭建一个可视化大屏项目毕竟 Vue 一直在更新自己搭建的可以使用最新版本的 Vue ,如果对版本没有太多要求的小伙伴们选择那些开源项目的基础上去修改也是很不错的。其次自己搭建一个项目可以更好的了解具体的实现方式。当然这个项目中还是会引用一些组件库。

创建 Vue3 + TypeScript + Vite 项目

这里就不过多去介绍了创建项目大家都会我这里就使用 WebStorm 去创建一个项目node 我选用 18.6.0版本的
Vue3 创建新项目

项目创建好之后我们先来引入一个组件库 DataV Vue3。这个组件库是在 DataV 的基础上重构的

引入 DataV Vue3

  • 首先为什选择 DataV Vue3 是因为 DataV 虽然有 Vue2Vue3React 各个版本的但是 Vue3 版本的不支持 Vite
  • 其次为什么要使用 DataV Vue3 是因为这里为我们封装好了一些酷炫的边框、装饰、图表之类的组件我们可以拿过来直接使用
  • 安装
npm install @kjgl77/datav-vue3
  • 全局引入(也可以按需引入考虑到每个页面都可能会用到所以这里直接在 main.ts 中全局引入)
// main.ts中全局引入
import { createApp } from 'vue'
import DataVVue3 from '@kjgl77/datav-vue3'

const app = createApp(App)

app.use(DataVVue3)
app.mount('#app')

接下来就该屏幕适配的问题了虽然 DataV Vue3 中有全局容器 <dv-full-screen-container>但是官方文档中建议在全屏容器内使用百分比搭配 flex 进行布局以便于在不同的分辨率下得到较为一致的展示效果。 并且使用前请注意将 body 的 margin 设为 0 否则会引起计算误差全屏后不能完全充满屏幕。我还是倾向于直接使用 px 或者 vw、vh 布局所以打算自己去进行屏幕的适配。

屏幕适配

屏幕适配大概有这几种方式rem、scale、vw 和 vh、以及 DataV Vue3 中的全局容器这些方式都可以很好的去进行适配具体选用哪种方法就看各人的喜好以及项目的需求了。个人比较推荐 scale 这种方式所以这里就采用 scale 方式来进行屏幕适配

scale 方式

实现思路

scale 方式大家都知道就是等比例缩放。一般情况下我们的设计稿尺寸都是 1920*1080 具体尺寸可以提前和 UI 沟通好我们就以这个尺寸作为我们需要保持的默认的宽高比例然后我们使用 window.innerWidth 、 window.innerHeight 获取浏览器窗口内部的宽度和高度之后根据浏览器窗口内部的宽高比和默认的宽高比来计算出需要缩放的比例就可以了。

代码

我们对其进行封装提取在 utils 文件夹中新建一个 scalingRatio.ts 文件

import { ref } from 'vue'

export default function useDraw() {
  // 指向最外层容器
  const appRef = ref()
  // 定时函数
  const timer = ref(0)
  // 默认缩放值
  const scale = {
    width: '1',
    height: '1',
  }
  // 设计稿尺寸px
  const baseWidth = 1920
  const baseHeight = 1080

  // 需保持的比例
  const baseProportion = parseFloat((baseWidth / baseHeight).toFixed(5))
  const calcRate = () => {
    // 当前宽高比
    const currentRate = parseFloat((window.innerWidth / window.innerHeight).toFixed(5))
    if (appRef.value) {
      if (currentRate > baseProportion) {
        // 表示更宽
        scale.width = ((window.innerHeight * baseProportion) / baseWidth).toFixed(5)
        scale.height = (window.innerHeight / baseHeight).toFixed(5)
        appRef.value.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`
      } else {
        // 表示更高
        scale.height = ((window.innerWidth / baseProportion) / baseHeight).toFixed(5)
        scale.width = (window.innerWidth / baseWidth).toFixed(5)
        appRef.value.style.transform = `scale(${scale.width}, ${scale.height}) translate(-50%, -50%)`
      }
    }
  }

  const resize = () => {
    clearTimeout(timer.value)
    timer.value = setTimeout(() => {
      calcRate()
    }, 200)
  }

  // 改变窗口大小重新绘制
  const windowDraw = () => {
    window.addEventListener('resize', resize)
  }

  // 改变窗口大小重新绘制
  const unWindowDraw = () => {
    window.removeEventListener('resize', resize)
  }

  return {
    appRef,
    calcRate,
    windowDraw,
    unWindowDraw
  }
}

接下来就是 CSS 部分以及使用封装的方法来进行屏幕适配这里需要把宽高改为你自己的设计稿的宽高

<!--app.vue-->
<script setup lang="ts">
import { RouterView } from 'vue-router'
</script>

<template>
  <div class="app">
    <RouterView />
  </div>
</template>
<style lang="scss" scoped>
.app {
  width: 100vw;
  height: 100vh;
  background-color: #000;
  overflow: hidden;
}
</style>
<!--index.vue-->
<script lang="ts" setup>
import {
  onMounted,
  onUnmounted,
} from 'vue'
// 引入封装好的方法
import useDraw from '@/utils/useDraw'
// 适配处理
const { appRef, calcRate, windowDraw, unWindowDraw } = useDraw()
// 生命周期
onMounted(() => {
  windowDraw()
  calcRate()
})

onUnmounted(() => {
  unWindowDraw()
})

</script>
<div id="index" ref="appRef">
  <!--  页面内容-->
</div>
<style>
#index{
  color: #d3d6dd;
  /*根据设计稿的宽高进行修改*/
  width: 1920px; 
  height: 1080px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  transform-origin: left top;
}
</style>

图表组件

安装 eCharts

npm i echarts --save 

全局引入以及挂载

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

import DataVVue3 from '@kjgl77/datav-vue3'

// 引入全局样式
import './assets/scss/style.scss';
// 引入 eCharts
import * as echarts from 'echarts'

const app = createApp(App)

/*
* 全局挂载 eCharts
* 这里需要注意的是挂载之前不能连缀 use()和 mount()也就是挂载要写到 use() 之前
* */
app.config.globalProperties.$echarts = echarts
app.use(DataVVue3)
app.use(router)

app.mount('#app')

使用

因为 Vue3 是组合 API ,所以要引入对应的 getCurrentInstance 去使用挂载到全局的图表组件

<script lang="ts" setup>
import {
  onMounted,
  ref,
  getCurrentInstance
} from 'vue'
const { proxy }: any = getCurrentInstance()
const decorationColors = ['#568aea', '#000000']
const title = '可视化大屏项目示例'
const eacharts1 = ref(null)
const renderChart = () => {
  var myChart = proxy.$echarts.init(eacharts1.value);
  myChart.setOption({
    title: [
      {
        text: '极坐标柱状图标签'
      }
    ],
    polar: {
      radius: [30, '80%']
    },
    radiusAxis: {
      max: 4
    },
    angleAxis: {
      type: 'category',
      data: ['a', 'b', 'c', 'd'],
      startAngle: 75
    },
    tooltip: {},
    series: {
      type: 'bar',
      data: [2, 1.2, 2.4, 3.6],
      coordinateSystem: 'polar',
      label: {
        show: true,
        position: 'middle',
        formatter: '{b}: {c}'
      }
    },
    animation: false
  })
};
onMounted(() => {
  renderChart()
})
</script>
<template>
  <div class="eacharts1" ref="eacharts1" style="width: 500px;height: 500px;"></div>
</template>

到这里所需的东西基本就都 OK 了我们就可以开始我们的大屏项目布局以及后续开发了。这里的屏幕适配的实现方式参考了 vue-big-screen 的实现方式。如果不使用 vite ,也可以直接使用 vue-big-screen 提供的源码进行删减然后开发使用。
此 Demo 已上传至个人 GitHub 需要的可自取。更多文章由于只是 Demo 所以在样式方面并没有过多的去调整

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: vue