前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从零开始:使用 Vue-ECharts 实现数据可视化图表功能

从零开始:使用 Vue-ECharts 实现数据可视化图表功能

原创
作者头像
喵喵侠
发布2024-06-26 18:51:06
3363
发布2024-06-26 18:51:06
举报

目录

前言

你好,我是喵喵侠。在前端开发中,经常会接到图表相关的页面需求,你需要在页面上绘制不同类型的图表,来丰富页面数据的呈现效果。通过图表你可以很直观的看到数据的大体情况,可以很方便的将数据进行多维度的对比。接下来我会为你介绍Vue-ECharts,看完本文后你能够快速上手开发。

为什么选择 Vue-ECharts

Vue-ECharts 是一个基于 Apache ECharts 和 Vue.js 的图表库。ECharts 是由百度开发并开源的一个强大的图表库,它支持多种类型的图表和丰富的交互效果。Vue-ECharts 则是将 ECharts 与 Vue.js 进行结合,使得在 Vue 项目中使用 ECharts 变得更加方便和高效。

相比较于原版的 Echarts,Vue-Echarts 有以下优点:

  • 简化开发:相比直接使用 JavaScript 引入 ECharts,Vue-ECharts 提供了更简洁的语法和更强的组件化支持,符合 Vue 的开发习惯。
  • 响应式数据绑定:利用 Vue 的响应式特性,数据的更新可以自动反映在图表上,无需手动更新。
  • 更好的集成:通过 Vue-ECharts,可以更方便地在 Vue 组件中使用 ECharts,实现图表的动态更新和交互。

简单来说,你可以用更少的代码书写,来实现同样的图表效果。只不过在书写方面,和原版有些不同之处。不过没关系,我将带你手把手实现一个柱状图案例,这样你就能很快明白其中的细节差异了。

案例:Vue-Echart开发一个分组柱状图

安装依赖

首先,我们需要在 Vue 项目中安装 Vue-ECharts 以及 ECharts:

代码语言:vue
复制
npm install vue-echarts echarts

注意,这两个都要安装,只安装vue-echarts是不行的。

引入

全局引入

你可以在 main.js中,进行全局引入。

如果你是 Echarts 4.x,可以这样写:

代码语言:vue
复制
// 引入 Echarts 4.x
import echarts from 'echarts'
Vue.prototype.$echarts = echarts

如果是 5.x,可以这样写:

代码语言:vue
复制
// 引入 Echarts 5.x
import * as echarts from 'echarts'
Vue.prototype.$echarts = echarts
代码语言:vue
复制
// 引入vue-echarts
import ECharts from 'vue-echarts'
Vue.component('v-chart', ECharts)

按需引入

你也可以在单个页面或者组件中,局部引入你所需要的组件。比方说这里的案例是柱状图,我可以这样写:

代码语言:vue
复制
// 从 echarts/core 导入必要的函数和组件
import { use, graphic } from 'echarts/core'

// 导入用于在画布上渲染图表的渲染器
import { CanvasRenderer } from 'echarts/renderers'

// 导入你想要使用的图表类型,在这里是柱状图
import { BarChart } from 'echarts/charts'

// 导入图表的各种组件,如标题、提示和图例
import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'

// 从 vue-echarts 导入 VChart 组件用于 Vue 集成
import VChart from 'vue-echarts'

// 注册导入的组件到 echarts 中
use([CanvasRenderer, BarChart, TitleComponent, TooltipComponent, LegendComponent])

按需引入需要你对每个模块有一定的了解,比方说柱状图是属于BarChart,需要用到标题、图例组件等,如果是其他类型的图表,引入的组件会有所不同。

编写组件

除了上面的引入,其他的写法跟 Echarts 大差不差,一个简单的组件示例如下:

代码语言:vue
复制
<v-chart autoresize :data="data" :option="defaultOption" />

data代表传入的数据,option 表示配置项,:auto-resize="true"代表图表自适应宽度。

我根据实际业务需求,开发了一个支持分组显示的柱状图组件,传入的数据可以是单柱,也可以是多柱。组件代码如下:

代码语言:vue
复制
<!-- 纵向柱状图多柱 -->
<template>
  <div class="vChartVerticalBar">
    <v-chart :auto-resize="true" :data="data" :option="defaultOption" />
  </div>
</template>

<script>
import { use, graphic } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import { BarChart } from 'echarts/charts'
import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'
import VChart from 'vue-echarts'
use([CanvasRenderer, BarChart, TitleComponent, TooltipComponent, LegendComponent])

export default {
  name: 'vChartVerticalBar',
  components: { VChart },
  props: {
    option: {
      type: Object,
      default: function () {
        return {}
      },
    },
    data: {
      type: Object,
      default: function () {
        return {
          categories: ['被删', '哈士奇', '杨不易呀', '三掌柜', '花花', '喵喵侠'],
          series: [
            {
              name: '2023',
              data: [233, 340, 666, 100, 340, 30],
            },
            {
              name: '2024',
              data: [233, 566, 666, 200, 300, 330],
            },
          ],
        }
      },
    },
  },
  data() {
    return {}
  },
  created() {},
  mounted() {},
  computed: {
    defaultOption() {
      let that = this
      const colorGradients = [
        this.generateGradient('#188df0', '#83bff6'),
        this.generateGradient('#f08d1a', '#ffaf7b'),
        this.generateGradient('#0d1a4f', '#4a69bd'),
        this.generateGradient('#83bff6', '#188df0'),
        this.generateGradient('#ffaf7b', '#f08d1a'),
      ]
      const series = this.data?.series?.map((serie, index) => {
        return {
          type: 'bar',
          // showBackground: true,
          name: serie.name,
          itemStyle: {
            barBorderRadius: [20, 20, 0, 0],
            color: new graphic.LinearGradient(0, 1, 0, 0, colorGradients[index % 5]),
          },
          label: {
            show: false,
            position: 'top',
          },
          barWidth: '20%',
          data: serie.data,
        }
      })
      return {
        grid: {
          left: '3%',
          right: '4%',
          top: '25%',
          bottom: '1%',
          containLabel: true,
        },
        tooltip: {
          formatter: function (params) {
            const unit = that.option.unit ?? '' // 设置单位,可以根据需求修改
            let res = params[0].name + '<br/>'
            for (let i = 0; i < params.length; i++) {
              res += params[i].marker + params[i].seriesName + ' : ' + params[i].value + unit + '<br/>'
            }
            return res
          },
          trigger: 'axis',
          axisPointer: {
            type: 'shadow',
          },
        },
        legend: {
          icon: 'circle',
          textStyle: {
            padding: [0, 0, 0, -8], // 设置图例文字与图例符号之间的间距,[上, 右, 下, 左]
          },
          itemGap: 20, // 设置图例和图例之间间距
        },
        yAxis: [
          {
            type: 'value',
            name: that.option.yAxisName || '',
            minInterval: this.option.minInterval || '', // 坐标轴最小间隔大小。
            nameTextStyle: {
              padding: [0, 24, 0, 0],
            },
            axisLine: {
              show: false,
            },
            axisTick: {
              show: false,
            },
            splitLine: {
              show: true,
              lineStyle: {
                //分割线
                color: '#DCDFE6',
                width: 1,
                type: 'dashed', //dotted:虚线 solid:实线
              },
            },
            axisLabel: {
              textStyle: {
                color: '#556677',
              },
              formatter: '{value}',
            },
          },
        ],
        xAxis: [
          {
            type: 'category',
            axisLabel: {
              color: '#858B9C',
              fontSize: '12',
              formatter: function (params) {
                let newParamsName = '' // 最终拼接成的字符串
                const paramsNameNumber = params.length // 实际标签的个数
                const provideNumber = that.option.provideNumber ||  6 // 每行能显示的字的个数
                const rowNumber = Math.ceil(paramsNameNumber / provideNumber) // 换行的话,需要显示几行,向上取整
                /**
                 * 判断标签的个数是否大于规定的个数, 如果大于,则进行换行处理 如果不大于,即等于或小于,就返回原标签
                 */
                // 条件等同于rowNumber>1
                if (paramsNameNumber > provideNumber) {
                  /** 循环每一行,p表示行 */
                  for (let p = 0; p < rowNumber; p++) {
                    let tempStr = '' // 表示每一次截取的字符串
                    const start = p * provideNumber // 开始截取的位置
                    const end = start + provideNumber // 结束截取的位置
                    // 此处特殊处理最后一行的索引值
                    if (p == rowNumber - 1) {
                      // 最后一次不换行
                      tempStr = params.substring(start, paramsNameNumber)
                    } else {
                      // 每一次拼接字符串并换行
                      tempStr = params.substring(start, end) + '\n'
                    }
                    newParamsName += tempStr // 最终拼成的字符串
                  }
                } else {
                  // 将旧标签的值赋给新标签
                  newParamsName = params
                }
                //将最终的字符串返回
                return newParamsName
              },
            },
            splitLine: {
              show: false,
            },
            axisTick: {
              show: false,
            },
            axisLine: {
              show: false,
            },
            data: that.data.categories,
          },
        ],
        series: series || [],
      }
    },
  },
  watch: {},
  methods: {
    // 生成渐变颜色的方法
    generateGradient(startColor, endColor) {
      return [
        { offset: 0, color: startColor },
        { offset: 0.5, color: startColor },
        { offset: 1, color: endColor },
      ]
    },
  },
}
</script>
<style lang="less" scoped>
.vChartVerticalBar {
  width: 100%;
  height: 100%;
}
</style>

效果图如下:

我上面的代码里面,this.option.xxx都是可以自定义的配置,比方说可以设置 x 轴标签文字单行显示长度;可以配置多柱的颜色,我用了一个渐变色数组取余循环,想要换成纯色改下也是可以的。基本上只要是 Echarts 可以支持的修改配置项,你都可以通过 Vue-Echarts 来实现。

总结

通过本文的介绍,你应该已经了解了 Vue-ECharts 的基本用法,以及如何在 Vue 项目中使用它来快速开发图表。相比直接使用 JavaScript 引入 ECharts,Vue-ECharts 提供了更简洁的语法和更强的组件化支持,使得数据的响应式更新变得更加简单。最关键的是,这是官方出品的,在我写这篇文章的时候去瞄了一眼,发现上次更新是3周前,说明更新是很频繁的,有问题官方也会及时解决优化。希望这些知识能够帮助您在实际项目中更好地进行数据可视化开发,有任何问题,欢迎在文章下方评论留言。


我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 前言
  • 为什么选择 Vue-ECharts
  • 案例:Vue-Echart开发一个分组柱状图
    • 安装依赖
    • 引入
      • 全局引入
        • 按需引入
          • 编写组件
          • 总结
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档