You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

126 lines
2.4 KiB

<template>
<div ref="chartContainer" class="pie-chart-container"></div>
</template>
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import * as echarts from 'echarts'
// 定义组件props
interface Props {
chartData?: Array<{ name: string; value: number }>
title?: string
}
const props = withDefaults(defineProps<Props>(), {
chartData: () => [],
title: ''
})
const chartContainer = ref<HTMLDivElement | null>(null)
let chartInstance: echarts.ECharts | null = null
// 初始化图表
const initChart = () => {
if (chartContainer.value) {
chartInstance = echarts.init(chartContainer.value)
updateChart()
}
}
// 更新图表
const updateChart = () => {
if (!chartInstance || !props.chartData) return
const option = {
title: {
// text: props.title,
left: 'center',
textStyle: {
color: '#FFF'
}
},
tooltip: {
trigger: 'item'
},
legend: {
show: true,
type: 'scroll', // 👈 开启可滚动图例
orient: 'vertical', // 👈 垂直排列
right: 10,
top: 'center',
textStyle: {
color: '#FFF'
}
},
series: [
{
name: props.title,
type: 'pie',
radius: ['30%', '50%'],
center: ['35%', '50%'], // 👈 左移饼图避免与图例重叠
avoidLabelOverlap: true,
itemStyle: {
borderRadius: 0,
borderColor: '#fff',
borderWidth: 1
},
label: {
show: true,
formatter: '{b}\n{d}%',
fontSize: 10
},
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
}
},
labelLine: {
show: true
},
data: props.chartData
}
]
}
chartInstance.setOption(option, true)
}
// 窗口大小改变时重置图表大小
const handleResize = () => {
if (chartInstance) {
chartInstance.resize()
}
}
// 监听数据变化
watch(
() => props.chartData,
() => {
updateChart()
},
{ deep: true }
)
// 初始化和销毁
onMounted(() => {
initChart()
window.addEventListener('resize', handleResize)
})
onBeforeUnmount(() => {
if (chartInstance) {
chartInstance.dispose()
}
window.removeEventListener('resize', handleResize)
})
</script>
<style scoped>
.pie-chart-container {
width: 100%;
height: 100%;
}
</style>