Vue3 + echarts 5.4.2 实现图表效果

简介: 从vue2升级到vue3,对原来的柱状图、折线图组件进行了修改,这两个组件的语法保留了vue2,实际使用也没有问题

从vue2升级到vue3,对原来的柱状图、折线图组件进行了修改,这两个组件的语法保留了vue2,实际使用也没有问题。

1、通用柱状图 BarChart.vue

<template>
  <div :class="className" :style="{height: height, width: width}"/>
</template>

<script>
    import * as echarts from 'echarts';
    import 'echarts/theme/macarons.js'

    export default {
   
   
        props: {
   
   
            className: {
   
   
                type: String,
                default: 'chart'
            },
            width: {
   
   
                type: String,
                default: '100%'
            },
            height: {
   
   
                type: String,
                default: '450px'
            },
            title: {
   
   
                type: String,
                required: true
            },
            chartData: {
   
   
                type: Object,
                required: true
            }
        },
        data() {
   
   
            // vue3需要这样写,否则`tooltip`无效
            chart: null
            return {
   
   
                // chart: null
            }
        },
        watch: {
   
   
            chartData: {
   
   
                deep: true,
                handler(val) {
   
   
                    this.setOptions(val)
                }
            }
        },
        mounted() {
   
   
            this.$nextTick(() => {
   
   
                this.initChart()
            })
        },
        beforeDestroy() {
   
   
            if (!this.chart) {
   
   
                return
            }
            this.chart.dispose()
            this.chart = null
        },
        methods: {
   
   
            initChart() {
   
   
                this.chart = echarts.init(this.$el, 'macarons')
                this.chart.setOption({
   
   
                    title: {
   
   
                        text: this.title,
                        textStyle: {
   
   
                            fontSize: 15
                        }
                    },
                    toolbox: {
   
   
                        show: true,
                        orient: 'horizontal',
                        left: 'right',
                        top: 'top',
                        feature: {
   
   
                            mark: {
   
    show: true },
                            magicType: {
   
    show: true, type: ['line', 'bar'] },
                        }
                    },
                    tooltip: {
   
   
                        trigger: 'axis',
                        axisPointer: {
   
   
                            type: 'shadow'
                        }
                    },
                    grid: {
   
   
                        top: '10%',
                        left: '2%',
                        right: '2%',
                        bottom: '4%',
                        containLabel: true
                    },
                    xAxis: [{
   
   
                        type: 'category',
                        axisTick: {
   
    show: false },
                    }],
                    yAxis: [{
   
   
                        type: 'value',
                    }],
                    series: []
                })
            },
            setOptions(data) {
   
   
                let map = data.map
                let series = []
                map.forEach((val, key) => {
   
   
                    let obj = {
   
   
                        name: key,
                        data: Array.from(val),
                        type: 'bar',
                        barWidth: '10%',
                        barGap: 0,
                        emphasis: {
   
   
                            focus: 'series'
                        },
                        animationDuration: 2800,
                        animationEasing: 'quadraticOut'
                    }
                    series.push(obj)
                });

                this.chart.setOption({
   
   
                    xAxis: [{
   
   
                        data: data.date,
                    }],
                    legend: {
   
   
                        data: Array.from(map.keys())
                    },
                    series: series
                })
            }
        }
    }
</script>

2、通用的折线图组件 LineChart.vue

<template>
  <div :class="className" :style="{height: height, width: width}"/>
</template>

<script>
    import * as echarts from 'echarts';
    import 'echarts/theme/macarons.js'

    export default {
   
   
        props: {
   
   
            className: {
   
   
                type: String,
                default: 'chart'
            },
            width: {
   
   
                type: String,
                default: '100%'
            },
            height: {
   
   
                type: String,
                default: '450px'
            },
            title: {
   
   
                type: String,
                required: true
            },
            chartData: {
   
   
                type: Object,
                required: true
            }
        },
        data() {
   
   
            // vue3需要这样写,否则`tooltip`无效
            chart: null
            return {
   
   
                // chart: null
            }
        },
        watch: {
   
   
            chartData: {
   
   
                deep: true,
                handler(val) {
   
   
                    this.setOptions(val)
                }
            }
        },
        mounted() {
   
   
            this.$nextTick(() => {
   
   
                this.initChart()
            })
        },
        beforeDestroy() {
   
   
            if (!this.chart) {
   
   
                return
            }
            this.chart.dispose()
            this.chart = null
        },
        methods: {
   
   
            initChart() {
   
   
                this.chart = echarts.init(this.$el, 'macarons')
                this.chart.setOption({
   
   
                    title: {
   
   
                        text: this.title,
                        textStyle: {
   
   
                            fontSize: 15
                        }
                    },
                    xAxis: {
   
   
                        type: 'category',
                        boundaryGap: false,
                    },
                    grid: {
   
   
                        left: 15,
                        right: 10,
                        bottom: 20,
                        top: '10%',
                        containLabel: true
                    },
                    toolbox: {
   
   
                        show: true,
                        orient: 'horizontal',
                        left: 'right',
                        top: 'top',
                        feature: {
   
   
                            mark: {
   
    show: true },
                            magicType: {
   
    show: true, type: ['line', 'bar'] },
                        }
                    },
                    tooltip: {
   
   
                        trigger: 'axis',
                        axisPointer: {
   
   
                            type: 'shadow'
                        },
                    },
                    yAxis: {
   
   
                        type: 'value',
                        axisTick: {
   
   
                            show: false
                        }
                    },
                    series: []
                })
            },
            setOptions(data) {
   
   
                let map = data.map
                let series = []
                map.forEach((val, key) => {
   
   
                    let obj = {
   
   
                        name: key,
                        data: Array.from(val),
                        type: 'line',
                        barWidth: '40',
                        smooth: true,
                        itemStyle: {
   
   
                            normal: {
   
   
                                lineStyle: {
   
   
                                    width: 2
                                }
                            }
                        },
                        animationDuration: 2800,
                        animationEasing: 'quadraticOut'
                    }
                    series.push(obj)
                });

                this.chart.setOption({
   
   
                    xAxis: {
   
   
                        data: data.date,
                    },
                    series: series
                })
            }
        }
    }
</script>

3、通用饼图组件 PieChart.vue

<template>
  <div :class="className" :style="{height:height,width:width}"/>
</template>

<script>
    import * as echarts from 'echarts';
    import 'echarts/theme/macarons.js'

    const color = [
        "#37a2da",
        "#32c5e9",
        "#9fe6b8",
        "#ffdb5c",
        "#ff9f7f",
        "#fb7293",
        "#e7bcf3",
        "#8378ea"
    ];
    export default {
   
   
        props: {
   
   
            className: {
   
   
                type: String,
                default: 'chart'
            },
            width: {
   
   
                type: String,
                default: '100%'
            },
            height: {
   
   
                type: String,
                default: '350px'
            },
            title: {
   
   
                type: String,
                required: true
            },
            chartData: {
   
   
                type: Object,
                required: true
            }
        },
        data() {
   
   
            return {
   
   
                chart: null
            }
        },
        watch: {
   
   
            chartData: {
   
   
                deep: true,
                handler(val) {
   
   
                    this.setOptions(val)
                }
            }
        },
        mounted() {
   
   
            this.$nextTick(() => {
   
   
                this.initChart()
            })
        },
        beforeDestroy() {
   
   
            if (!this.chart) {
   
   
                return
            }
            this.chart.dispose()
            this.chart = null
        },
        methods: {
   
   
            initChart() {
   
   
                this.chart = echarts.init(this.$el, 'macarons')
                this.chart.setOption({
   
   
                    title: {
   
   
                        textStyle: {
   
   
                            fontSize: 15
                        }
                    },
                    tooltip: {
   
   
                        trigger: 'item',
                        formatter: '{b} : {c} ({d}%)'
                    },
                    itemStyle: {
   
   
                        normal:{
   
   
                            borderRadius: 10,
                            borderColor: '#fff',
                            borderWidth: 2
                        },
                    },
                    label: {
   
   
                        color: '#32c5e9'
                    },
                    labelLine: {
   
   
                        lineStyle: {
   
   
                            width: 2
                        }
                    },
                    grid: {
   
   
                        top: '10%',
                        left: '2%',
                        right: '2%',
                        bottom: '4%',
                        containLabel: true
                    },
                    series: [{
   
   
                        type: "pie",
                        radius: [50, 110],
                        center: ['50%', '50%'],
                        top: 10,
                        itemStyle: {
   
   
                            normal:{
   
   
                                color: item => {
   
   
                                    return color[item.dataIndex%(color.length)]
                                },
                                borderRadius: 10,
                                borderColor: '#fff',
                                borderWidth: 2
                            },
                        },
                        label: {
   
   
                            color: '#32c5e9'
                        },
                        labelLine: {
   
   
                            lineStyle: {
   
   
                                width: 2
                            }
                        },
                        emphasis: {
   
   
                            label: {
   
   
                                show: true,
                                fontSize: '20',
                                fontWeight: 'bold',
                            }
                        },
                        animationEasing: 'cubicInOut',
                        animationDuration: 2600
                    }]
                })
            },
            setOptions(data) {
   
   
                this.chart.setOption({
   
   
                    title: {
   
   
                        text: this.title,
                    },
                    series: [{
   
   
                        data: data,
                    }]
                })
            }
        }
    }
</script>

4、调用示例

<template>
  <div class="dashboard-editor-container">
    <el-row :gutter="32">
      <el-col :xs="24" :sm="24" :lg="24">
        <div class="chart-wrapper">            
          <el-radio-group v-model="period" @change="getData" style="margin: 0 0 20px 0">
            <el-radio-button label="30">30</el-radio-button>
            <el-radio-button label="180">180</el-radio-button>
            <el-radio-button label="365">365</el-radio-button>
          </el-radio-group>

          <line-chart :chart-data="lineChartData" :title="`每日任务接收情况统计`"/>
        </div>
      </el-col>
    </el-row>

    <el-row :gutter="32">
      <el-col :xs="24" :sm="24" :lg="24">
        <div class="chart-wrapper">
          <bar-chart :chart-data="monthlyData" :title="`近半年统计月报`"/>
        </div>
      </el-col>
    </el-row>

    <el-row :gutter="32">
      <el-col :xs="24" :sm="24" :lg="8">
        <div class="chart-wrapper">
          <pie-chart :chart-data="diagnosePieChartData" :title="`诊断任务统计`"/>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script setup name="Index">
    import LineChart from './LineChart'
    import BarChart from './BarChart'
    import PieChart from './PieChart'

    import {
   
   
        countByMonthly,
        countByReceiptTime,
        countByTypeAndDept
    } from '@/api/xxx'

    const {
   
   proxy} = getCurrentInstance();
    const period = ref(180)
    const monthlyData = ref({
   
   });
    const lineChartData = ref({
   
   });
    const diagnosePieChartData = ref({
   
   });

    function getData() {
   
   
        lineChartData.value = {
   
   }
        countByReceiptTime(period.value).then(res => {
   
   
            let arr = res.data
            let date = arr.map(item => item.time);
            let data = arr.map(item => item.total);

            let map = new Map();
            map.set('每日接收任务', data);

            lineChartData.value = {
   
   
                date,
                map
            };
        })
    }

    function monthly() {
   
   
        monthlyData.value = {
   
   };
        countByMonthly().then(res => {
   
   
            let arr = res.data
            let date = arr.map(item => item.item);
            let data1 = arr.map(item => item["xx"]);
            let data2 = arr.map(item => item["xx"]);
            let data3 = arr.map(item => item["xx"]);
            let data4 = arr.map(item => item["xx"]);
            let data5 = arr.map(item => item["xx"]);

            let map = new Map();
            map.set('任务总数', data1);
            map.set('未开始', data2);
            map.set('进行中', data3);
            map.set('已完成', data4);
            map.set('已发布', data5);

            monthlyData.value = {
   
   
                date,
                map
            };
        })
    }

    function typeAndDept() {
   
   
        diagnosePieChartData.value = {
   
   }
        countByTypeAndDept().then(res => {
   
   
            let arr = res.data;
            diagnosePieChartData.value = arr.filter(item => item.type === 'diagnose').map(item => {
   
   
                return {
   
   "name": item.dept, "value": item.total}
            });
        })
    }

    getData();
    monthly();
    typeAndDept();
</script>

<style lang="scss" scoped>
  .dashboard-editor-container {
   
   
    padding: 32px;
    background-color: rgb(240, 242, 245);
    position: relative;

    .chart-wrapper {
   
   
      background: #fff;
      padding: 16px 16px 0;
      margin-bottom: 32px;
    }
  }

  @media (max-width: 1024px) {
   
   
    .chart-wrapper {
   
   
      padding: 8px;
    }
  }
</style>

5、实现效果:

  • 折线图
    image.png
  • 柱状图
    image.png

  • 饼图
    image.png

相关文章
|
5天前
|
存储 JavaScript 数据可视化
vue3+echarts应用——深度遍历html的dom结构并用树图进行可视化
vue3+echarts应用——深度遍历html的dom结构并用树图进行可视化
44 1
|
5天前
|
数据可视化 JavaScript 前端开发
Echarts是一个开源的JavaScript可视化库,用于创建各种类型的图表
Echarts是JavaScript的开源可视化库,Python通过Pyecharts库可调用它来绘制图表。示例展示了如何用Pyecharts创建柱状图:定义图表对象,设置标题和坐标轴,添加X轴、Y轴数据,最后渲染展示。Pyecharts还支持折线图、散点图、饼图等多种图表类型,更多详情可查阅官方文档。
33 0
|
5天前
|
前端开发 JavaScript 定位技术
Docusaurus框架——react+antd+echarts自定义mdx生成图表代码解释文档
Docusaurus框架——react+antd+echarts自定义mdx生成图表代码解释文档
28 0
|
5天前
|
数据采集 数据可视化 小程序
vue3+echarts可视化——记录我的2023编程之旅
vue3+echarts可视化——记录我的2023编程之旅
29 1
|
5天前
|
存储
vue2、vue3分别配置echarts多图表的同步缩放(二)
vue2、vue3分别配置echarts多图表的同步缩放
20 0
|
5天前
|
API
vue2、vue3分别配置echarts多图表的同步缩放(一)
vue2、vue3分别配置echarts多图表的同步缩放
18 0
|
5天前
|
容器
echarts图表怎样实现刷新功能?
echarts图表怎样实现刷新功能?
|
5天前
|
数据可视化
echarts图表坐标轴数据标签添加下划线
echarts图表坐标轴数据标签添加下划线
67 0
|
5天前
|
前端开发 JavaScript BI
Django教程第5章 | Web开发实战-数据统计图表(echarts、highchart)
使用echarts和highcharts图表库实现折线图、柱状图、饼图和数据集图
71 2