1 代码
<template>
<div class="main">
<div class="pie-charts" :id="chartId" />
</div>
</template>
<script>
export default {
props: {
mapTitle: [String, Array],
divideBy: [Number, String],
distance: {
type: Number,
default: 260,
},
alpha: {
type: Number,
default: 16,
},
beta: {
type: Number,
default: 60,
},
pieDataFlag: {
type: Boolean,
default: false,
},
optionData: {
type: Array,
default: () => [],
},
chartId: {
type: [String, Number],
default: () => new Date().getTime(),
},
unit: {
type: String,
default: () => "",
},
chart: {
type: String,
default: () => null,
},
eventName: {
type: Function,
default: null,
},
},
data() {
return {
localChartId: this.chartId,
localEventName: this.eventName,
isUpdating: false,
};
},
mounted() {
this.setPie(this.optionData, this.chartId, this.chart, this.eventName);
},
methods: {
setPie(pieData, id, myChart, eventName) {
if (myChart) myChart.dispose();
var option = this.getPie3D(pieData);
option.series.push({
backgroundColor: "transparent",
name: "pie2d",
type: "pie",
label: { opacity: 1, overflow: "none" },
itemStyle: { opacity: 0.02 },
labelLine: { length: 20, length2: 10 },
startAngle: -60,
clockwise: false,
radius: ["30%", "55%"],
center: ["50%", "50%"],
data: pieData,
tooltip: {
show: false,
},
});
myChart = this.$echarts.init(document.getElementById(id));
myChart.setOption(option);
myChart.off("click");
myChart.on("click", (params) => eventName(params, this.mapTitle));
window.addEventListener("resize", () => myChart.resize());
},
getPie3D(pieData) {
let series = [];
let sumValue = 0;
let startValue = 0;
let endValue = 0;
let k = 1;
pieData.sort((a, b) => {
return b.value - a.value;
});
for (let i = 0; i < pieData.length; i++) {
sumValue += pieData[i].value;
let seriesItem = {
name: typeof pieData[i].name === "undefined" ? `series${i}` : pieData[i].name,
type: "surface",
parametric: true,
wireframe: {
show: false,
},
pieData: pieData[i],
pieStatus: {
selected: false,
hovered: false,
k: k,
},
radius: "50%",
center: ["10%", "10%"],
};
if (typeof pieData[i].itemStyle != "undefined") {
let itemStyle = {};
typeof pieData[i].itemStyle.color != "undefined" ? (itemStyle.color = pieData[i].itemStyle.color) : null;
typeof pieData[i].itemStyle.opacity != "undefined"
? (itemStyle.opacity = pieData[i].itemStyle.opacity)
: null;
seriesItem.itemStyle = itemStyle;
}
series.push(seriesItem);
}
for (let i = 0; i < series.length; i++) {
endValue = startValue + series[i].pieData.value;
series[i].pieData.startRatio = startValue / sumValue;
series[i].pieData.endRatio = endValue / sumValue;
series[i].parametricEquation = this.getParametricEquation(
series[i].pieData.startRatio,
series[i].pieData.endRatio,
false,
false,
k,
series[i].pieData.value
);
startValue = endValue;
}
let boxHeight = this.getHeight3D(series, 30);
let option = {
labelLine: {
show: true,
lineStyle: {
color: "#fff",
normal: {},
},
},
label: {
show: true,
position: "outside",
formatter:(params)=>{
return `{d|${params.value}}{c|(亩)} \n {c|${params.name}} `
},
rich: {
d: {
fontSize: 22,
lineHeight: 18,
fontFamily: "Source Han Sans",
fontWeight: "bold",
color: "#6DC1F9",
marginBottom:10
},
c: {
fontSize: 12,
color: "#B4CAD1",
}
},
},
tooltip: {
position: "right",
textStyle: { color: "#fff", fontSize: 14 },
borderWidth: 1,
borderColor: "#1495F4",
backgroundColor: "rgba(20, 149, 244, 0.5)",
boxShadow: "0 0 3px rgba(0, 0, 0, 0.3)",
extraCssText: "box-shadow: inset 0px 0px 10px 0px rgba(1, 30, 18, 0.302);",
formatter:(params)=>{
return `${params.seriesName
}<br/>${option.series[params.seriesIndex].pieData.value}(亩)`;
}
},
xAxis3D: {
min: -1,
max: 1,
},
yAxis3D: {
min: -1,
max: 1,
},
zAxis3D: {
min: -1,
max: 1,
},
grid3D: {
show: false,
boxHeight: boxHeight,
left: 0,
top: 0,
viewControl: {
alpha: this.alpha,
beta: this.beta || 60,
distance: this.distance,
rotateSensitivity: 0,
zoomSensitivity: 0,
panSensitivity: 0,
},
},
series: series,
};
return option;
},
getHeight3D(series, height) {
series.sort((a, b) => {
return b.pieData.value - a.pieData.value;
});
return (height * 25) / series[0].pieData.value;
},
getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
let midRatio = (startRatio + endRatio) / 2;
let startRadian = startRatio * Math.PI * 2;
let endRadian = endRatio * Math.PI * 2;
let midRadian = midRatio * Math.PI * 2;
if (startRatio === 0 && endRatio === 1) {
isSelected = true;
}
k = typeof k !== "undefined" ? k : 1 / 3;
let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
let hoverRate = isHovered ? 1.05 : 1;
return {
u: {
min: -Math.PI,
max: Math.PI * 3,
step: Math.PI / 32,
},
v: {
min: 0,
max: Math.PI * 2,
step: Math.PI / 20,
},
x: function (u, v) {
if (u < startRadian) {
return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
},
y: function (u, v) {
if (u < startRadian) {
return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
if (u > endRadian) {
return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
}
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
},
z: function (u, v) {
if (u < -Math.PI * 0.5) {
return Math.sin(u);
}
if (u > Math.PI * 2.5) {
return Math.sin(u) * h * 0.1;
}
return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
},
};
},
},
};
</script>
<style lang="less" scoped>
.main {
width: 100%;
height: 100%;
.pie-charts {
width: 100%;
height: 100%;
}
}
</style>
2使用案例
testArr: [
{
name: '一产',
value: 16050,
unit: '万个',
impoConsSort: '0101',
itemStyle: { color: '#53AFF8' }
},
{
name: '二产',
value: 10000,
unit: '万个',
impoConsSort: '0101',
itemStyle: { color: '#61D4E6' }
}
]
![使用的案例](https://img-blog.csdnimg.cn/direct/b8f907b72b6246d993a4fe5b7ac72239.jpeg#pic_center)
![效果图](https://img-blog.csdnimg.cn/direct/bc0ecb38c8f9460d8da7c0398c7ba06c.jpeg#pic_center)