vue二次封装echarts组件 线 + 柱 + 叠混合图(自适应大小)

效果图

1.子组件html

<template>
    <div :id="id" ref="chartRef" :style="{ height: '100%', width: '100%', }"></div>
</template>

2.子组件js

<script setup lang="ts">
/**
 * id
 * xAxisList,x轴数据
 * seriesDataList,y轴数据
 * legend,图例数据
 * dateList,标签数据
 * 这几个参数必须传
 * 
 */
import * as echarts from 'echarts';
import { onMounted, defineProps, ref, watch, nextTick } from 'vue'

const props = defineProps({
    id: {
        type: String,
        default: 'barChart'
    },
    xAxisList: {
        type: Object,
        default: ['浙江1', '北京1', '上海1', '广东1', '深圳1'],
    },
    seriesDataList: {
        type: Object,
        default: [
            [2000, 7100, 6200, 7300, 7400],
            [8000, 8200, 8400, 8600, 8800],
            [6000, 6500, 7000, 7500, 8000],
            [7011, 7500, 8000, 8500, 9000],
        ]
    },
    legend: {
        type: Object,
        default: ['收入', '毛利润', '收入增长率', '利润增长率']
    },
    dateList: {
        type: Object,
        default: ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05']
    },
    units: {
        type: String,
        default: ''
    },
    charttype: {
        type: String,
        default: 'bar'
    },
    lastcharttype: {
        type: String,
        default: 'bar'
    },
    stack: {
        type: Boolean,
        default: false
    },
    dataZoom: {
        type: Boolean,
        default: false

    },
    max: {
        type: [Number, String],
        default: undefined,
    },
    // chartsData:{
    //     type:Object,
    //     default:{
    //         dateList:['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05'],
    //         legend:['收入', '毛利润', '收入增长率', '利润增长率'],
    //         seriesDataList:[
    //             [2000, 7100, 6200, 7300, 7400],
    //             [8000, 8200, 8400, 8600, 8800],
    //             [6000, 6500, 7000, 7500, 8000],
    //             [7011, 7500, 8000, 8500, 9000], 
    //         ],
    //         xAxisList:['浙江1', '北京1', '上海1', '广东1', '深圳1']
    //     },
    // }
});
const chartRef = ref<any>('')
let echart = echarts
watch(
    () => [props.seriesDataList, props.xAxisList, props.units + props.legend],
    () => {
        //解决警告 There is a chart instance already initialized on the dom.
        // nextTick()
        echart.dispose(document.getElementById(props.id) as HTMLDivElement)
        initChart()
    },
    { deep: true }
)
const colorArr = ['#02c7af', '#62D256', '#FFC550', '#FF8853', '#FF6B8E', '#BF7E7E', '#D177CB', '#9E86DF', '#6881FF', '#91A1B1', '#5EB2E9']
// let idElem:any=''
onMounted(() => {
    initChart()
});
let Echarts: any = null
let initChart = () => {
    // nextTick()
    if (Echarts) {
        Echarts.dispose()
    }
    Echarts = null
    // if(!chartRef.vlaue) return false
    Echarts = echarts.init(document.getElementById(props.id) as HTMLDivElement)
    let options: any = {
        title: {
            show: props.seriesDataList.length > 0 ? false : true,
            text: '暂无数据',
            textStyle: {
                color: '#888888'
            },
            // subtext: 'Fake Data',
            left: 'center',
            top: '50%'
        },
        grid: {
            left: '2%',
            right: '5%',
            bottom: '4%',
            containLabel: true,
        },
        tooltip: {
            trigger: 'axis',
            backgroundColor: "rgba(255,255,255, 0)",
            padding: 0,
            formatter: (param: any) => {
                let tmp = ''
                param.map((item: any) => {//
                    tmp += `
              <span style="display: flex; align-items: center; margin: 0 0 0 0;">
                ${item.marker}
                <span style="color: #333; margin: 0 30px 0 0;">${item.seriesName}</span>
                <span style="color: #777777; font-weight: bold;">${item.value}</span>
              </span>
              `
                })
                return `
            <div style="min-width: 167px; font-size: 14px; border-radius: 4px; box-shadow: 0 1px 5px #00000029; background-color: white; padding: 15px; font-size: 14px; display: flex; flex-direction: column; justify-content: space-between;">
                <span style="color: #999999;">${props.dateList[param[0].dataIndex]}</span>`
                    + tmp +
                    `</div>
            `;
            },
        },
        legend: {
            x: 'center',
            //   y: 'top',
            top: 10,
            padding: [5, 5, 5, 40],
            data: props.legend,
            textStyle: {
                color: '#999'
            }
        },
        xAxis: [
            {
                type: 'category',
                boundaryGap: props.charttype == 'line' ? false : true,
                data: props.xAxisList,
                splitLine: {
                    show: false,
                    lineStyle: {
                        color: "#dcdcdc",
                        width: 1,
                        type: "solid",
                    },
                },

            }
        ],
        yAxis: [{
            type: 'value',
            name: props.units,
            min: 0,
            /*  max:(value:any)=>{
 
                 return (props.max=='undefined'|| props.max==undefined)?undefined:props.max
             }, */
            splitLine: {
                lineStyle: {
                    color: "#dcdcdc",
                    type: "solid",
                },
            },
        }, {
            show: false,
            type: 'value',
            name: props.units,
            min: 0,
            /*  max:(value:any)=>{
 
             return (props.max=='undefined'|| props.max==undefined)?undefined:props.max
             }, */
            splitLine: {
                show: false,
                lineStyle: {
                    color: "#dcdcdc",
                    type: "solid",
                },
            },
        }],
        dataZoom: props.dataZoom == true ? [
            {
                type: 'inside',
                start: 0,
                end: 10
            },
            {
                start: 0,
                end: 10
            }
        ] : [],
        series: props.seriesDataList.map((item: any, index: any) => {
            return {
                data: item,
                type: (props.seriesDataList.length == index + 1) ? props.lastcharttype : props.charttype,
                stack: props.stack ? 'die' : 'die' + index,//判断堆叠图lastcharttype
                smooth: true,
                yAxisIndex: (props.seriesDataList.length == index + 1 && props.lastcharttype == 'line' && props.seriesDataList.length > 1) ? 1 : 0,
                name: props.legend[index],
                color: colorArr[index],
            }
        })
    };
    Echarts.setOption(options)
    const resizeObserver = new ResizeObserver((entries) => {
        let elwidth = entries[0].contentRect.width
        setTimeout(() => {
            Echarts.resize({ width: elwidth, height: "auto" })
        }, 300);
    })
    let idElem = document.getElementById(props.id) as HTMLDivElement
    resizeObserver.observe(idElem);
}


</script>

3.引用

import BarChart from '@/components/barChart.vue'
<BarChart
          v-if="xAxisList.length > 0"
          id="barChartClass"
          :xAxisList="xAxisList"
          :seriesDataList="seriesDataListTemp"
          :legend="legendTemp"
          :dateList="dateList"
          :stack="typeDataList != null ? true : false"
          :charttype="'bar'"
          :lastcharttype="'bar'"
          :units="'元'"
          >
</BarChart>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值