vue3+ts项目封装echarts饼图

下载echarts 

npm i echarts

饼图对应type为pie

成果图: (数据为动态展示所以要封装组件)

 封装组件 为 EPIPieChart.vue

封装组件 通用代码

<template>

</template>

<script setup lang="ts">
import echarts from '@/assets/ts/echarts';
import { nextTick, reactive, watch } from 'vue';

const props = defineProps({
     pid: {
        type: String,
        required: true
    },
    online: {
        type: Number,
        required: true
    },
    offline: {
        type: Number,
        required: true
    }
})

watch([() => props.online, () => props.offline], (newVal) => {
    option.series[0].data[0].value = props.online;
    option.series[0].data[1].value = props.offline;
    initChart();
})

let dataList: { name: string }[] = reactive([]);

nextTick(() => {
    const container = document.querySelector('#' + props.pid) as HTMLElement;
    
    initChart(container);
/*
 if (container) {
        initChart(container);
    }
*/
});

const option = {
//echarts配置项
}
let myChart: echarts.ECharts | null = null;
const initChart = (container?: HTMLElement) => {
    if (!myChart) myChart = echarts.init(container as HTMLElement);
    myChart.setOption(option)
}
}
</script>

<style lang="scss" scoped>
</style>

详细代码如下

<template></template>

<script setup lang="ts">
import { nextTick } from 'vue';
import echarts from '@/assets/ts/echarts';
import { ZRColor } from 'echarts/types/dist/shared';
import useResizeChart from '@/components/CommonChart/hooks/useResizeChart';

const props = defineProps({
    // 父容器ID 此处为声明所需要的变量
    pid: {
        type: String,
        required: true,
    },
    title: {
        type: String,
        required: true,
    },
    curData: {
        type: Object,
        required: true,
    },
    preData: {
        type: Object,
        required: true,
    },
    sequential: {
        type: Number,
        required: true,
    },
    // 饼图 颜色
    color: {
        type: Array as () => ZRColor[],
        default: [],
    },
});

// 环比 此处需要两组数据,所以添加两个对象

const data = [
    {
        value: props.curData.value,
        label: props.curData.value + ' kW·h',
        name: props.curData.title,
    },
    {
        value: props.preData.value,
        label: props.preData.value + ' kW·h',
        name: props.preData.title,
    },
];

nextTick(() => {
    const container = document.querySelector('#' + props.pid) as HTMLElement;
    if (container) {
        const myChart = echarts.init(container);
        const upIcon = new URL('../../assets/img/Profile/Charts/up.svg', import.meta.url).href;
        const downIcon = new URL('../../assets/img/Profile/Charts/down.svg', import.meta.url).href;

//此处可以根据需要自定义echarts的option类型
        const option = {
            color: props.color,
            title: [
                {
                    text: ` 环比 {${props.sequential > 0 ? 'upIcon' : 'downIcon'}|}`,
                    subtext: props.sequential + '%',

                    top: '40%',
                    left: 'center',
                    textStyle: {
                        fontSize: 12,
                        color: '#fff',
                        fontWeight: 500,
                        rich: {
                            upIcon: {
                                height: 10,
                                backgroundColor: {
                                    image: upIcon,
                                },
                            },
                            downIcon: {
                                height: 10,
                                backgroundColor: {
                                    image: downIcon,
                                },
                            },
                        },
                    },
                    subtextStyle: {
                        fontSize: 14,
                        color: '#fff',
                    },
                },
            ],
            // tooltip: {
            //     trigger: 'item',
            //     formatter: function (parms: any) {
            //         const str = parms.marker + '' + parms.name + '</br>' + '用电量:' 
             + parms.data.value + ' kW·h' + '</br>' + '占比:' + parms.percent + '%';
            //         return str;
            //     },
            // },
            legend: {
                // type: 'scroll',
                icon: 'circle',
                orient: 'horizontal',
                formatter: '{name}用电量',
                textStyle: {
                    color: '#fff',
                },
                bottom: 0,
                height: 250,
            },
            series: [
                {
                    // 新增: 外环
                    name: '',
                    type: 'pie',
                    radius: ['58%'],
                    itemStyle: {
                        color: 'transparent',
                        borderWidth: 1,
                        borderColor: '#0fc7c0',
                    },
                    data: [100],
                    animation: false,
                    // showBackground: true,
                    // backgroundStyle: {
                    //     color: 'rgba(66, 66, 66, .3)',
                    // },
                },
                {
                    // 新增: 内环
                    name: '',
                    type: 'pie',
                    radius: ['32%'],
                    avoidLabelOverlap: false,
                    itemStyle: {
                        color: 'transparent',
                        borderWidth: 1,
                        borderColor: '#0fc7c0',
                    },
                    data: [100],
                    animation: false,
                },
                {
                    // 数据环
                    name: props.title,
                    type: 'pie',
                    radius: ['35%', '55%'],
                    clockwise: false,

                    // 指示线
                    label: {
                        show: true,
                        position: 'outside',
                        fontSize: 12,
                        lineHeight: 16,
                        color: '#fff',
                        formatter: '{name|{b}}\n{c}\n',
                        rich: {
                            name: {
                                color: 'inherit', //此时inherit表示文字颜色使用父级对应的值
                            },
                        },
                    },

                    // 新增: 指示线的样式
                    labelLine: {
                        show: true,
                        lineStyle: {
                            type: 'dashed', //指示线为虚线
                        },
                    },

                    // 新增: 饼图的样式
                    itemStyle: {
                        borderRadius: 10,
                        borderColor: '#071629',
                        borderWidth: 4,
                    },
                    emphasis: {
                        scale: false,
                    },
                    data: data,
                },
            ],
        };
        // 是否显示 饼图外环
        // if (props.showRing) {
        //     ringData.forEach(item => {
        //        option.series.unshift(item);
        //     });
        // }
        myChart.setOption(option);
        // 自适应 chart
        useResizeChart(container, myChart as echarts.ECharts);
    }
});
</script>

<style lang="scss" scoped></style>

使用组件

<div id="day-total-electricity">
  <EPIPieChart pid="day-total-electricity" title="当日用电量"
 :curData="dayElectricity.cur" :preData="dayElectricity.pre" :sequential="siteData.dayCompare" :color="dayColor"></EPIPieChart>
    </div>
<div id="month-total-electricity">
    <EPIPieChart pid="month-total-electricity" title="当月用电量" :curData="monthElectricity.cur" :preData="monthElectricity.pre" :sequential="siteData.monthCompare" :color="monthColor"></EPIPieChart>
       </div>




<script lang="ts" setup>
// 用电概况
//声明日用电量所用的两种颜色
const dayColor = ['#ea713d', '#07ffd5'];
const dayElectricity = computed(() => ({
    cur: {
        title: '当日',
        value: siteData.value.EPITodaySum,
    },
    pre: {
        title: '昨日',
        value: siteData.value.EPIYesterdaySum,
    },
}));
const monthColor = ['#ff6f92', '#42d3f0'];
const monthElectricity = computed(() => ({
    cur: {
        title: '当月',
        value: siteData.value.EPIThisMonthSum,
    },
    pre: {
        title: '上月',
        value: siteData.value.EPILastMonthSum,
    },
}));
</script>

 

useResizeChart.ts文件

 用于自适应 echarts 图表大小

import echarts from "@/assets/ts/echarts";
export default function useResizeChart(container: HTMLElement, chart: echarts.ECharts) {

    // 监听容器大小变化
    const resizeObserver = new ResizeObserver(entries => {
        // 重新设置大小
        chart.resize({
            animation: {
                duration: 500
            }
        });
    });

    resizeObserver.observe(container);

    // onBeforeUnmount(() => {
    // 	// 销毁前解除监听
    // 	resizeObserver.unobserve(container);
    // })

}

猜你喜欢

转载自blog.csdn.net/weixin_68531033/article/details/127651697