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.

268 lines
6.6 KiB

<template>
<div class="bodycontainer">
<div class="labels">
<div
class="label-item"
v-for="(item, index) in pieData"
:key="index"
:style="{
backgroundImage: `url(${require('@/assets/sentimeent/' +
(item.name === '小程序' ? '其他' : item.name) +
'.png')})`,
backgroundSize: '100% 100%',
}"
>
<div class="label-content">
<div class="percent" :style="{ color: getItemColor(index) }">
{{ getItemPercent(item) }}%
</div>
<div class="name">{{ item.name }}</div>
</div>
</div>
</div>
<div class="chart-container">
<div ref="chart" style="width: 400px; height: 300px;"></div>
</div>
</div>
</template>
<script>
import * as echarts from "echarts";
export default {
data() {
return {
chart: null,
total: 0,
currentSelected: null,
pieData: [
{ value: 15, name: "上级下发" },
{ value: 3, name: "部门转发" },
{ value: 10, name: "小程序" },
{ value: 4, name: "无效" },
],
colorMap: ["#37a4ff", "#00ffde", "#ff7e2b", "#fbe84f"],
};
},
computed: {
legendData() {
return this.pieData.map((item) => ({
name: item.name,
value: item.value,
color: item.color,
}));
},
},
mounted() {
this.calculateTotal();
this.initChart();
},
methods: {
calculateTotal() {
this.total = this.pieData.reduce((sum, item) => sum + item.value, 0);
},
initChart() {
this.chart = echarts.init(this.$refs.chart);
const option = {
tooltip: {
trigger: "item",
formatter: "{a} <br/>{b}: {c} ({d}%)",
},
series: [
{
name: "数据集",
type: "pie",
radius: ["50%", "70%"],
avoidLabelOverlap: false,
itemStyle: {
borderRadius: 10,
borderColor: "#fff",
borderWidth: 2,
},
label: {
show: false,
position: "center",
},
emphasis: {
label: {
show: true,
fontSize: "18",
fontWeight: "bold",
formatter: (params) => {
const percentage = ((params.value / this.total) * 100).toFixed(1);
return `{b|${params.name}}\n{hr|}\n{d|${percentage}%}`;
},
rich: {
b: {
fontSize: 16,
fontWeight: "bold",
color: "#333",
lineHeight: 26,
},
hr: {
borderColor: "#fff",
width: "100%",
borderWidth: 1,
height: 0,
},
d: {
fontSize: 16,
color: "#333",
lineHeight: 26,
},
},
},
},
data: this.pieData.map((item) => ({
value: item.value,
name: item.name,
itemStyle: { color: item.color },
})),
},
],
graphic: [
{
type: "text",
left: "center",
top: "center",
style: {
text: `总模块\n${this.total}`,
textAlign: "center",
fill: "#333",
fontSize: 18,
fontWeight: "bold",
},
},
],
};
this.chart.setOption(option);
// 添加点击事件
this.chart.on("click", (params) => {
this.currentSelected = params;
this.updateCenterText();
});
// 响应式调整
window.addEventListener("resize", this.resizeHandler);
},
updateCenterText() {
if (this.currentSelected) {
const percentage = ((this.currentSelected.value / this.total) * 100).toFixed(1);
const option = {
graphic: [
{
type: "text",
left: "center",
top: "center",
style: {
text: `${this.currentSelected.name}\n${percentage}%`,
textAlign: "center",
fill: this.currentSelected.color,
fontSize: 18,
fontWeight: "bold",
},
},
],
};
this.chart.setOption(option);
} else {
const option = {
graphic: [
{
type: "text",
left: "center",
top: "center",
style: {
text: `总模块\n${this.total}`,
textAlign: "center",
fill: "#333",
fontSize: 18,
fontWeight: "bold",
},
},
],
};
this.chart.setOption(option);
}
},
resizeHandler() {
this.chart && this.chart.resize();
},
getItemColor(index) {
return this.colorMap[index] || "#ffffff";
},
getItemPercent(item) {
const total = this.pieData.reduce((sum, i) => sum + i.value, 0);
if (total === 0) return 0;
let percent = (item.value / total) * 100;
// 保留一位小数
return percent.toFixed(1);
},
},
beforeDestroy() {
window.removeEventListener("resize", this.resizeHandler);
this.chart && this.chart.dispose();
},
};
</script>
<style lang="scss" scoped>
.bodycontainer {
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
.labels {
display: flex;
justify-content: space-between;
padding: 0 20px;
.label-item {
position: relative;
width: 170px;
height: 65px;
display: flex;
justify-content: center;
align-items: center;
.label-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.percent {
font-size: 28px;
font-weight: bold;
font-family: Arial;
line-height: 1.2;
margin-top: -10px;
}
.name {
font-family: AlibabaPuHuiTiR;
font-size: 20px;
color: #b4f9ff;
line-height: 22px;
text-align: justifyLeft;
font-style: normal;
text-transform: none;
margin-top: 5px;
}
}
}
}
.chart-container {
width: 400px;
height: 300px;
margin-top: 20px;
}
}
</style>