1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
| <!-- 环形图 -->
| <template>
| <div
| ref="chartRef"
| class="relative w-full"
| :style="{ height: props.height }"
| v-loading="props.loading"
| >
| </div>
| </template>
|
| <script setup>
| import { useChartOps, useChartComponent } from '@/hooks/core/useChart'
| defineOptions({ name: 'ArtRingChart' })
| const props = defineProps({
| height: { required: false, default: useChartOps().chartHeight },
| loading: { required: false, default: false },
| isEmpty: { required: false, default: false },
| colors: { required: false, default: () => useChartOps().colors },
| data: { required: false, default: () => [] },
| radius: { required: false, default: () => ['50%', '80%'] },
| borderRadius: { required: false, default: 10 },
| centerText: { required: false, default: '' },
| showLabel: { required: false, default: false },
| showTooltip: { required: false, default: true },
| showLegend: { required: false, default: false },
| legendPosition: { required: false, default: 'right' }
| })
| const { chartRef, isDark, getAnimationConfig, getTooltipStyle, getLegendStyle } =
| useChartComponent({
| props,
| checkEmpty: () => {
| return !props.data?.length || props.data.every((item) => item.value === 0)
| },
| watchSources: [() => props.data, () => props.centerText],
| generateOptions: () => {
| const getCenterPosition = () => {
| if (!props.showLegend) return ['50%', '50%']
| switch (props.legendPosition) {
| case 'left':
| return ['60%', '50%']
| case 'right':
| return ['40%', '50%']
| case 'top':
| return ['50%', '60%']
| case 'bottom':
| return ['50%', '40%']
| default:
| return ['50%', '50%']
| }
| }
| const option = {
| tooltip: props.showTooltip
| ? getTooltipStyle('item', {
| formatter: '{b}: {c} ({d}%)'
| })
| : void 0,
| legend: props.showLegend ? getLegendStyle(props.legendPosition) : void 0,
| series: [
| {
| name: '数据占比',
| type: 'pie',
| radius: props.radius,
| center: getCenterPosition(),
| avoidLabelOverlap: false,
| itemStyle: {
| borderRadius: props.borderRadius,
| borderColor: isDark.value ? '#2c2c2c' : '#fff',
| borderWidth: 0
| },
| label: {
| show: props.showLabel,
| formatter: '{b}\n{d}%',
| position: 'outside',
| color: isDark.value ? '#ccc' : '#999',
| fontSize: 12
| },
| emphasis: {
| label: {
| show: false,
| fontSize: 14,
| fontWeight: 'bold'
| }
| },
| labelLine: {
| show: props.showLabel,
| length: 15,
| length2: 25,
| smooth: true
| },
| data: props.data,
| color: props.colors,
| ...getAnimationConfig(),
| animationType: 'expansion'
| }
| ]
| }
| if (props.centerText) {
| const centerPos = getCenterPosition()
| option.title = {
| text: props.centerText,
| left: centerPos[0],
| top: centerPos[1],
| textAlign: 'center',
| textVerticalAlign: 'middle',
| textStyle: {
| fontSize: 18,
| fontWeight: 500,
| color: isDark.value ? '#999' : '#ADB0BC'
| }
| }
| }
| return option
| }
| })
| </script>
|
|