parent
07010b14ff
commit
7bab8e176a
@ -0,0 +1,171 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="className" :style="{height:height,width:width}"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
require('echarts/theme/macarons') // echarts theme
|
||||||
|
import resize from '@/views/dashboard/components/mixins/resize'
|
||||||
|
const animationDuration = 6000
|
||||||
|
export default {
|
||||||
|
mixins: [resize],
|
||||||
|
props: {
|
||||||
|
className: String,
|
||||||
|
height: String,
|
||||||
|
width: String,
|
||||||
|
percent: [Number,String],
|
||||||
|
chartData: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
text: String,
|
||||||
|
subText: String
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
flag: true,
|
||||||
|
chart: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.initChart()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initChart() {
|
||||||
|
this.chart = echarts.init(this.$el, 'macarons');
|
||||||
|
this.setOptions();
|
||||||
|
|
||||||
|
},
|
||||||
|
setOptions() {
|
||||||
|
this.chart.setOption(this.options)
|
||||||
|
this.setGraphics()
|
||||||
|
},
|
||||||
|
setGraphics () {
|
||||||
|
const getPointOnCircle = (angle, radiusPercent) => {
|
||||||
|
let radian = (angle - 90 - 12) * Math.PI / 180;
|
||||||
|
let radius = this.chart.getWidth() / 2 * radiusPercent / 100;
|
||||||
|
let x = this.chart.getWidth() / 2 + Math.cos(radian) * radius;
|
||||||
|
let y = this.chart.getHeight() / 2 + Math.sin(radian) * radius;
|
||||||
|
return {x: x, y: y};
|
||||||
|
}
|
||||||
|
let graphicElements = [];
|
||||||
|
let total = 0;
|
||||||
|
if (!this.options?.series[0]?.data) return;
|
||||||
|
this.options?.series[0]?.data.forEach(function (item) {
|
||||||
|
total += item.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
let startAngle = 0;
|
||||||
|
this.options?.series[0]?.data.forEach(function (item) {
|
||||||
|
let angle = (item.value / total) * 360;
|
||||||
|
let endAngle = startAngle + angle;
|
||||||
|
let middleAngle = (startAngle + endAngle) / 2;
|
||||||
|
|
||||||
|
// 计算开始和结束点的位置
|
||||||
|
let pointStart = getPointOnCircle(middleAngle - angle / 2, 60);
|
||||||
|
let pointEnd = getPointOnCircle(middleAngle + angle / 2, 60);
|
||||||
|
|
||||||
|
// 添加小圆的装饰
|
||||||
|
graphicElements.push({
|
||||||
|
type: 'circle',
|
||||||
|
shape: {
|
||||||
|
cx: pointStart.x,
|
||||||
|
cy: pointStart.y,
|
||||||
|
r: 4
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
fill: '#fff'
|
||||||
|
},
|
||||||
|
z: 100
|
||||||
|
});
|
||||||
|
graphicElements.push({
|
||||||
|
type: 'circle',
|
||||||
|
shape: {
|
||||||
|
cx: pointEnd.x,
|
||||||
|
cy: pointEnd.y,
|
||||||
|
r: 4
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
fill: '#fff'
|
||||||
|
},
|
||||||
|
z: 100
|
||||||
|
});
|
||||||
|
|
||||||
|
startAngle += angle;
|
||||||
|
})
|
||||||
|
|
||||||
|
this.chart.setOption({
|
||||||
|
graphic: {
|
||||||
|
elements: graphicElements
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
options () {
|
||||||
|
const _this = this;
|
||||||
|
return {
|
||||||
|
legend: {
|
||||||
|
show: true,
|
||||||
|
bottom: 0,
|
||||||
|
left: "center",
|
||||||
|
orient: "horizontal",
|
||||||
|
itemWidth: 8,
|
||||||
|
itemHeight: 6
|
||||||
|
},
|
||||||
|
color: ["#446df6","#f2a93f","#56b7f9"],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['50%', '70%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
padAngle: 4,
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: 10,
|
||||||
|
padding: 10
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'center',
|
||||||
|
formatter: `${_this.title||""}\n${_this.title ? '' : '{b}'}{d}%`
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
fontSize: 15,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: (() => {
|
||||||
|
if (this.percent || this.percent === 0) {
|
||||||
|
return [
|
||||||
|
{ value: parseFloat(this.percent), name: '完成率' },
|
||||||
|
{ value: 100 - parseFloat(this.percent), name: '未完成率' }
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
return this.chartData
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
}
|
||||||
|
],
|
||||||
|
graphic: {
|
||||||
|
elements: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
chartData () {
|
||||||
|
this.setOptions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
||||||
|
After Width: | Height: | Size: 545 B |
|
After Width: | Height: | Size: 845 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
Loading…
Reference in new issue