如何在 Vue 3 中使用 ECharts 创建饼状图
实现高亮效果与交互
<template>
<div ref="chart" class="chart"></div>
</template>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import * as echarts from 'echarts';
const chart = ref(null);
let myChart = null;
let highlightInterval;
const data = reactive([{
name: '第三产业',
value: 51
}, {
name: '第二产业',
value: 29
}, {
name: '第一产业',
value: 20,
}])
let color2 = ['rgba(42,142,242,0.5)', 'rgba(101,147,254,0.5)', 'rgba(61,188,191,0.5)'];
let color1 = ['rgba(42,142,242,1)', 'rgba(101,147,254,1)', 'rgba(61,188,191,1)'];
const createBaseData = (data, colors) => {
let baseData = [];
for (let i = 0; i < data.length; i++) {
baseData.push({
value: data[i].value,
name: data[i].name,
itemStyle: {
normal: {
color: colors[i],
}
}
});
}
return baseData;
}
onMounted(() => {
myChart = echarts.init(chart.value);
let baseData1 = createBaseData(data, color1);
let baseData2 = createBaseData(data, color2);
const option = {
tooltip: {
show: true,
trigger: 'item',
formatter: (params) => {
const total = data.reduce((sum, current) => sum + current.value, 0);
params.percent = ((params.value / total) * 100).toFixed(0);
return `${params.name}\n${params.percent}%`;
}
},
legend: {
show: true,
selectedMode: false,
data: data.map(d => d.name),
orient: 'vertical',
right: '5%',
top: 'center',
icon: 'roundRect',
textStyle: {
fontSize: 14,
fontFamily: 'Arial',
rich: {
name: {
color: '#FFFFFF',
fontWeight: 'bold',
},
value: {
color: '#FFF200',
fontStyle: 'italic',
},
}
},
formatter: function (name) {
const item = data.find(d => d.name === name);
if (item) {
const total = data.reduce((sum, current) => sum + current.value, 0);
const percentage = ((item.value / total) * 100).toFixed(0);
return [
`{name|${name}} `,
`{value|${percentage}%}`
].join('');
}
return name;
},
},
series: [{
type: 'pie',
hoverAnimation: false,
radius: ['70%', '50%'],
center: ['35%', '50%'],
itemStyle: {
borderColor: '#fff',
borderWidth: 2
},
emphasis: {
itemStyle: {
color: 'rgba(255, 0, 0, 1)',
borderWidth: 5,
borderColor: '#ffffff',
shadowBlur: 20,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
label: {
show: true,
fontSize: 20,
fontWeight: 'bold',
rich: {
b: {
color: '#ffffff',
fontSize: 24,
},
c: {
color: '#ffffff',
fontSize: 20,
}
},
formatter: (params) => {
const total = data.reduce((sum, current) => sum + current.value, 0);
params.percent = ((params.value / total) * 100).toFixed(0);
return `{b|${params.percent}%}\n\n{c|${params.name}}`;
}
}
},
label: {
show: false,
position: 'center'
},
data: baseData1
},
{
type: 'pie',
hoverAnimation: false,
color: color1,
radius: ['95%', '71%'],
center: ['35%', '50%'],
tooltip: {
show: false
},
itemStyle: {
borderColor: '#fff',
borderWidth: 2
},
emphasis: {
itemStyle: {
color: 'rgba(255, 0, 0, 1)',
borderWidth: 5,
borderColor: '#ffffff',
shadowBlur: 20,
shadowColor: 'rgba(0, 0, 0, 0.5)',
},
label: {
show: true,
fontSize: 20,
fontWeight: 'bold',
rich: {
b: {
color: '#ffffff',
fontSize: 24,
},
c: {
color: '#ffffff',
fontSize: 20,
}
},
formatter: (params) => {
const total = data.reduce((sum, current) => sum + current.value, 0);
params.percent = ((params.value / total) * 100).toFixed(0);
return `{b|${params.percent}%}\n\n{c|${params.name}}`;
}
}
},
label: {
show: false,
position: 'center'
},
data: baseData2
},
]
};
myChart.setOption(option);
let currentIndex = 0;
const totalItems = data.length;
const startHighlighting = () => {
myChart.dispatchAction({
type: 'highlight',
seriesIndex: 0,
dataIndex: currentIndex
});
myChart.dispatchAction({
type: 'highlight',
seriesIndex: 1,
dataIndex: currentIndex
});
highlightInterval = setInterval(() => {
myChart.dispatchAction({
type: 'downplay',
seriesIndex: 0,
dataIndex: currentIndex
});
myChart.dispatchAction({
type: 'downplay',
seriesIndex: 1,
dataIndex: currentIndex
});
currentIndex = (currentIndex + 1) % totalItems;
myChart.dispatchAction({
type: 'highlight',
seriesIndex: 0,
dataIndex: currentIndex
});
myChart.dispatchAction({
type: 'highlight',
seriesIndex: 1,
dataIndex: currentIndex
});
}, 5000);
};
startHighlighting();
chart.value.addEventListener('mouseenter', () => {
clearInterval(highlightInterval);
myChart.dispatchAction({
type: 'downplay',
seriesIndex: 0,
dataIndex: currentIndex
});
myChart.dispatchAction({
type: 'downplay',
seriesIndex: 1,
dataIndex: currentIndex
});
});
chart.value.addEventListener('mouseleave', () => {
startHighlighting();
});
});