VUE3项目--实现数据大屏

192 阅读5分钟

一、概述

现代社会中,在越来越多的场景中会应用到数据大屏(即数据可视化)。本文讲述了在VUE3项目中,搭建数据大屏的全过程。使用的组件库有:DavaV、ECharts。
构建大屏的过程:

  1. 设计好页面布局
  2. 控制数据大屏的自适应
  3. 添加组件

二、设计页面布局

数据大屏页面布局很清晰,能很清楚的看出分了几个区域。现在以下面的大屏图为示例,说一下如何布局。

image.png

页面布局格式如下图:

布局.png

  • 整个数据大屏分为两行。第一行是标题行,第二行展示图表数据。
  • 第一行被等分为三块,中间展示标题,并居中。
  • 第二行被分为三大列,从左到右宽度比例为3:4:3。
  • 第二行第一列(最左列)内容垂直等分了三块,即图表1、图表2、图表3。他们的高度比例是:1:1:1。
  • 第二行第二列(中间列)内容垂直分了两块,即主图表、图表4,他们的高度比例是:2:1。
  • 第二行第三列(最右列)内容垂直分了两块,即图表5、图表6,他们的高度比例是:2:1。

在.vue文件中,布局代码如下:

<template>
  <div class="container">
    <!-- 数据大屏展示内容区域 -->
    <div class="screen" ref="screen">
      <!-- 第一行:展示标题 -->
      <div class="title">
        <div class="title-divide title-left">标题左侧</div>
        <div class="title-divide title-center">标题</div>
        <div class="title-divide title-right">标题右侧</div>
      </div>
      <!-- 第二行:展示图表数据 -->
      <div class="body">
        <!-- 该行的最外层分了三列,宽度比例是:3:4:3。 -->
        <!-- 一行三列 -->
        <div class="body-left">
          <!-- 在body-left块中垂直方向上均等分了三小块 -->
          <div class="body-left-top">图表1</div>
          <div class="body-left-middle">图表2</div>
          <div class="body-left-bottom">图表3</div>
        </div>
        <div class="body-center">
          <div class="body-center-top">主图表</div>
          <div class="body-center-bottom">图表4</div>
        </div>
        <div class="body-right">
          <div class="body-right-top">图表5</div>
          <div class="body-right-bottom">图表</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts" name="">
import { onMounted, ref } from 'vue';

// 获取数据大屏展示内容盒子的DOM元素
const screen = ref()

// 定义大屏缩放比例
function getScale(width = 1920, height = 1080) {
  const ww = window.innerWidth / width
  const wh = window.innerHeight / height

  return ww < wh ? ww : wh
}
// 动态调整screen div的尺寸
function screenResize() {
  // scale:进行缩放计算,基础尺寸:1980w * 1080h。
  // translate:元素平移,正数表示沿轴的正向移动。translate(-30%, -60%)以基点沿X轴反方向平移30%,沿Y轴反方向平移60%。
  screen.value.style.transform = `scale(${getScale()}) translate(-50%, -50%)`
}

onMounted(() => {
  screenResize()
})
// 监听视口尺寸的变化
window.onresize = () => {
  screenResize()
}
</script>

<style lang="scss" scoped>
// 最外层容器
.container {
  // 尺寸同视口一样
  height: 100vh;
  width: 100vw;

  .screen {
    // 设置一个基础的尺寸大小
    height: 1080px;
    width: 1920px;
    position: fixed;
    left: 50%;
    top: 50%;
    // 平移的基点:左上角
    transform-origin: left top;

    .title {
      height: 5%;
      width: 100%;
      display: flex;

      // 父容器样式已经指定display是flex。在三个子容器中样式指定flex: 1;,则会将父容器宽度进行三等分。
      .title-divide {
        flex: 1; // 长度等分
        height: 100%;
      }
      .title-left {
        background-color: pink;
      }
      .title-center {
        background-color: greenyellow;
      }
      .title-right {
        background-color: yellow;
      }
    }

    .body {
      height: 95%;
      width: 100%;
      display: flex;
      // 主轴方向:水平方向
      flex-direction: row;
      justify-content: space-between;

      // 父级容器样式已经设置display为flex
      .body-left {
        // 0: flex-grow放大比例。默认为0,不放大。
        // 1:flex-shrink缩小比例。默认为1。当空间不足时,所有子元素等比例缩小。
        // 30%:flex-basis在主轴方向上的基础尺寸
        flex: 0 1 30%;

        display: flex;
        // 主轴方向:垂直方向
        flex-direction: column;

        // .body-left-top、.body-left-middle、.body-left-bottom三个样式中都是flex:1。
        // 表示三个元素的方法比例都是1,即他们等分空间。
        .body-left-top {
          flex: 1;
          background-color: antiquewhite;
        }
        .body-left-middle {
          flex: 1;
          background-color: rgb(232, 250, 215);
        }
        .body-left-bottom {
          flex: 1;
          background-color: rgb(189, 193, 247);
        }
      }
      .body-center {
        flex: 0 1 40%;

        display: flex;
        // 主轴方向:垂直方向
        flex-direction: column;

        // .body-center-top、.body-center-bottom的样式中flex不一样。
        // 表示.body-center-top占据空间是.body-center-bottom的2倍。
        .body-center-top {
          flex: 2;
          background-color: rgb(242, 215, 250);
        }
        .body-center-bottom {
          flex: 1;
          background-color: rgb(215, 241, 250);
        }
      }
      .body-right {
        flex: 0 1 30%;

        display: flex;
        // 主轴方向:垂直方向
        flex-direction: column;

        // .body-right-top、.body-right-bottom的样式中flex不一样。
        // 表示.body-right-top占据空间是.body-right-bottom的2倍。
        .body-right-top {
          flex: 2;
          background-color: rgb(176, 177, 178);
        }
        .body-right-bottom {
          flex: 1;
          background-color: rgb(10, 141, 234);
        }
      }
    }
  }
}
</style>

代码效果图:

image.png

针对上述代码的说明:

  1. 页面布局使用flex布局。
  2. 数据大屏实现了适配(自适应),核心是使用scale设置缩放。

三、数据大屏的适配(自适应)

要想数据大屏实现适配,下面几个地方是关键。

  1. 最外层容器container设置高度、宽度是当前视口的高度和宽度。
  2. 第二层容器screen设置了一个基础尺寸(1980 * 1080),大屏的缩放都是以这个尺寸为基础进行的。
  3. 第二层容器screen设置了一个固定位置(position: fixed),并设置了一个平移基点transform-origin。
  4. 第二层容器screen内部的容器大小使用百分比设置。

四、添加组件

1、使用DataV

1.1 安装DataV

pnpm install @kjgl77/datav-vue3

全局引入

// main.ts中全局引入 
import { createApp } from 'vue' 
import DataVVue3 from '@kjgl77/datav-vue3' 

const app = createApp(App) 
app.use(DataVVue3) 
app.mount('#app')

引入后在.vue文件中可以直接使用
<dv-decoration-1 :color="['pink','yellow']" style="width:200px;height:50px;" />

2、使用ECharts

2.1 安装ECharts

pnpm install echarts --save
如果用到3D地球(globe)组件,还需要安装echarts-gl pnpm install echarts-el- --save

2.2 使用 ECharts

//在vue文件中,这样使用ECharts
<template>
  <div id="main" style="width: 600px;height:400px;"></div>
</template>
<script>
import * as echarts from 'echarts';

// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 绘制图表
myChart.setOption({
  title: {
    text: 'ECharts 入门示例'
  },
  tooltip: {},
  xAxis: {
    data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
  },
  yAxis: {},
  series: [
    {
      name: '销量',
      type: 'bar',
      data: [5, 20, 36, 10, 10, 20]
    }
  ]
});
</script>