vue管理系统封装echarts

本文介绍了如何在Vue项目中创建一个可配置的ECharts组件,支持动态数据渲染和导出图片到Excel,以及图表的自适应功能,以适应不同屏幕尺寸和菜单状态变化。
摘要由CSDN通过智能技术生成

创建个echartsComponent文件

<template>
    <div :class="['chart', {'img-chart': hasImgBase64}]">
        <div :id="uuid1" :class="['chart-show', {'img-chart-show': hasImgBase64}]"></div>
        <div v-if="hasImgBase64" :id="uuid2" :style="{ height: imgHeight, width: imgWidth }" class="img-chart-export"></div>
    </div>
</template>
<script>
import * as echarts from "echarts";
import { mapGetters } from 'vuex'
const get_uuid = () => {
    var s = [];
    var hexDigits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    for (var i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4";  
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); 
    s[8] = s[13] = s[18] = s[23] = "-";

    var uuid = s.join("");
    return uuid;
}
export default {
    name: "echarts-component",
    props: {
        option: {
            type: Object,
            default: null,
        },
        // 调用echarts是否需要导出到Excel文档里
        hasImgBase64: {
            type: Boolean,
            default: false,
        },
        imgWidth: {
            type: String,
            default: '1200px',
        },
        imgHeight: {
            type: String,
            default: '900px',
        },
    },
    data() {
        return {
            uuid1: null,
            uuid2: null,
            myChart: null,
            imagesBase64: null,
        };
    },
    computed: {
        ...mapGetters(['sidebar']),
    },
    created() {
            this.uuid1 = get_uuid(); 
            this.uuid2 = get_uuid(); 
    },
    watch: {
        option: {
            handler(val, oldVal) {
                this.option && this.drawChart()
                this.option && this.hasImgBase64 && this.drawChartImg()
            },
            immediate: true
        },
        /**
         * @description 左侧菜单缩放echarts自适应
         */
        'sidebar.opened': {
            handler(newVal) {
                this.debounce(this.chartResize, 300)
            }
        },
    },
  destroyed() {
      window.removeEventListener('resize', this.debounce(this.chartResize, 500))
  },
  methods: {
    chartResize() {
        if (this.myChart) {
            this.myChart.resize()
        }
    },
    debounce(fn, wait) {
        clearTimeout(this.timeout)
        this.timeout = setTimeout(fn, wait)
    },
    drawChart() {
        var dom = document.getElementById(this.uuid1)
        if(dom) {
            dom.removeAttribute('_echarts_instance_');
            if (this.myChart != null && this.myChart != "" && this.myChart != undefined) {
				this.myChart.dispose();//销毁实例,实例销毁后无法再被使用
            }
            setTimeout(() => {
                this.$nextTick(() => {
                    if(!this.hasImgBase64) {
                        // 首页 需要采用svg渲染,比canvans清晰度高
                        this.myChart = echarts.init(dom, null, {renderer: 'svg'})
                    } else {
                        this.myChart = echarts.init(dom)
                    }
                    if(this.myChart) {
                        this.myChart.setOption(this.option, true)
                        window.addEventListener('resize', () => {
                            this.debounce(this.chartResize, 300)
                        })
                    }
                })
            }, 300)
        }
    },
    // uuid2是为导出生成的固定宽高的折线图,无需考虑自适应
    drawChartImg() {
        var dom2 = document.getElementById(this.uuid2)
        if(dom2) {
            dom2.removeAttribute('_echarts_instance_');
            if (this.myImgChart != null && this.myImgChart != "" && this.myImgChart != undefined) {
				this.myImgChart.dispose();//销毁实例,实例销毁后无法再被使用
            }
            setTimeout(() => {
                this.$nextTick(() => {
                    this.myImgChart = echarts.init(dom2)
                    if(this.myImgChart) {
                        const imgOption = {
                            ...this.option,
                            animation: false
                        }
                        this.myImgChart.setOption(imgOption, true)
                        this.imagesBase64 = this.myImgChart.getDataURL() 
                        this.$emit('getChartImg', this.imagesBase64)
                    }
                })
            }, 300)
        }
    },
    // 左侧菜单缩放,切换其他页面,激活页面时activated调用该函数echarts自适应调用
    // 需要图表自适应都可调用
    sidebarChange(time) {
        this.debounce(this.chartResize, time ?? 300)
    },
  }
};
</script>
<style scoped lang="scss">
.chart {
    width:100%;
    height:100%;
    position:relative;
    &-show {
        position: absolute;
        width: 100%;
        height: 100%;
        > div{
            width: 100%;
            height: 100%;
        }
    }
}
.img-chart {
    overflow: hidden;
    &-show {
        background-color: #fff;
        z-index: 2;
    }
    &-export {
        position: absolute;
        width: 100%;
        height: 100%;
        z-index: 1;
        > div{
            width: 1200px;
            height: 800px;
        }
    }
}
</style>

在其他页面传入data即可调用

<echarts-component ref="homeRevenueCarChart" :option="option"></echarts-component>

 {
option = val ? val : [
    { value: 0, name: '0~3公里' },
    { value: 0, name: '3~6公里' },
    { value: 0, name: '6~10公里' },
    { value: 0, name: '10~15公里' },
    { value: 0, name: '15~25公里' },
    { value: 0, name: '25~35公里' },
    { value: 0, name: '大于等于35公里' }
  ]
  return {
    tooltip: {
        show:true,
        trigger: 'item',
        confine: true,
        borderWidth: 0,
        formatter: function(params){
            let tip = '';
            if(params.seriesIndex === 0){
                tip = params.marker + params.name + ":" + params.percent + '%'
            }else if(params.seriesIndex === 1){
                tip = ''
            }
            return tip ;
        }
    },
    legend: {
      textStyle: {
        padding:[fontSize(-8),0,0,0],
        height: fontSize(36),
        width: fontSize(64),
        backgroundColor: 'transparent',
        rich: {
            name: {
              fontSize: fontSize(12),
              padding:[fontSize(4),0,0,0], 
            },
            num: {
                fontSize: fontSize(16),
                fontWeight: 600,
                color: '#333',
                padding:[fontSize(-4),0,0,fontSize(-20)],
            }
        },
      },
      top: '50%',
      left: 'center',
      icon: 'rect',
      itemHeight: fontSize(10),
      itemWidth: fontSize(10),
      formatter: function (name) {
          const item = data.find(item => item.name === name)
          const num = item.value
          return [
            `{num| ${num} %}`, // 这里注意返回数组类型,内为对象,对象必须包裹成字符串,c为当前文字标识,| 后为你想显示的值
            `{name| ${name}}`,
          ].join('\n') // 换行
      }
    },
    graphic: {
        elements: [
            {
                type: 'image',
                style: {
                    image: require("../images/home_distance.png"),
                    // image: require("@/views/vehicleMonitor/home-page/assets/images/home_distance.png"),
                    width: fontSize(38),
                    height: fontSize(34),
                },
                left: '44.5%',
                top: '24%'
            }
        ]
    },
    color:['#165DFF', '#57E4F3', '#FF724B','#F6D449', '#FEAA38','#7F76FF','#E784FF'],
    series: [
      {
        type: 'pie',
        zlevel: 2, //层级
        radius: ['24%', '37%'],
        avoidLabelOverlap: false,
        center: ['50%', '30%'],
        itemStyle: {
            borderRadius: fontSize(8),
            normal: {
              // 饼状图阴影,值越大阴影亮度越高
              shadowBlur: fontSize(6),
              shadowColor: 'rgba(227, 228, 238, 0.1)'
            }
        },
        label: {
          show: false,
          position: 'center'
        },
        data: data,
      },
      // 外环
        {
            type: 'pie',
            // radius: ['23%', '40%'],
            radius: ['21%', '40%'],
            center: ['50%', '30%'],
            itemStyle: {
                normal: {
                    color: 'rgba(0,0,0,.06)',
                    label: {
                        show: false
                    },
                    labelLine: {
                        show: false
                    }
                },
            },
            hoverAnimation: false,
            data: [100],
        }
    ]
  }
}
  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值