封装一个百分比组件 发表于 2024-07-13 最近因为工作需要,封装了一个百分比组件。 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340<template> <!-- 左侧图标区 --> <div class="container"> <div ref="pieChart" id="charts"></div> <!-- 标题 --> <div class="custom-title" :style="chartOptions.titleStyle" v-if="chartOptions.isShowTitle" > {{ chartOptions.title }} </div> <!-- 总数 --> <div class="custom-total" :style="chartOptions.totalStyle" v-if="chartOptions.isShowTotal" > {{ chartOptions.total }} </div> <!-- 副标题 --> <div class="custom-subtitle" :style="chartOptions.subTitleStyle" v-if="chartOptions.isShowSubTitle" > {{ chartOptions.subTitle }} </div> <!-- 类型 --> <div class="custom-type" :style="chartOptions.typeStyle" v-if="chartOptions.isShowType" > {{ chartOptions.type }} </div> <!-- 百分数 --> <div class="custom-percent" :style="chartOptions.percentStyle" v-if="percent" > {{ percent }} </div> </div></template><script> import * as echarts from 'echarts' import { deepMerge } from '@/utils/index' export default { name: 'CgPercentChart', data() { return { backgroundColor: '#000236', // 图表底色 activeColor: '#eee305', // 实际数颜色 defaultColor: '#fe2a21', // 缺省值颜色 defaultOptions: {}, chartInstance: null, diff: 20, padAngle: 0, // 扇区间距 在chartOptions.isSpace为true的情况下起作用 } }, computed: { percent() { let diff = 0 if (this.chartOptions.isShowPoint) { diff = this.chartOptions.value / this.chartOptions.total } else { diff = (this.chartOptions.value / this.chartOptions.total).toFixed(2) } if (this.chartOptions.isShowPercent) { return `${diff * 100}%` } else { return `${diff * 100}` } }, }, props: { chartOptions: { type: Object, default: () => ({ title: '', // 标题 subTitle: '', // 副标题 total: '', // 总数 value: '', // 实际数 activeColor: '', // 实际值的扇区颜色 defaultColor: '', // 剩余值的扇区颜色 }), }, }, methods: { handleResize() { if (this.chartInstance) { this.chartInstance.resize() } }, // 初始化echarts initChart() { const chartContainer = this.$refs.pieChart this.chartInstance = echarts.init(chartContainer) this.updateChart() }, generateCirclePieSeries() { const diff = this.chartOptions.diff ? this.chartOptions.diff : this.diff const series = [ { name: '', type: 'pie', padAngle: this.chartOptions.padAngle || this.padAngle, startAngle: this.chartOptions.startAngle ? this.chartOptions.startAngle : 0, endAngle: this.chartOptions.endAngle ? this.chartOptions.endAngle : 0, // startAngle: 230, // endAngle: -50, clockWise: true, //顺时加载 hoverAnimation: false, //鼠标移入变大 radius: [`${80 - diff}%`, `80%`], center: ['50%', '42%'], label: { show: false, }, itemStyle: { label: { show: false, }, labelLine: { show: false, }, borderWidth: 5, }, data: [ { value: this.chartOptions.value, name: this.chartOptions.subTitle, itemStyle: { // color: this.chartOptions.activeColor // ? this.chartOptions.activeColor // : this.activeColor, color: this.chartOptions.isGrad ? new echarts.graphic.LinearGradient( 1, 0, 0, 0, this.chartOptions.gradientArr, false ) : this.chartOptions.activeColor, }, }, { value: this.chartOptions.total - this.chartOptions.value, name: '', itemStyle: { color: this.chartOptions.defaultColor ? this.chartOptions.defaultColor : this.defaultColor, borderWidth: 0, }, tooltip: { show: false, trigger: 'axis', backgroundColor: '#000342', textStyle: { color: '#fff', }, }, hoverAnimation: false, }, ], }, { name: '', type: 'pie', silent: true, z: 1, clockWise: true, //顺时加载 hoverAnimation: false, //鼠标移入变大 radius: [`${80 - diff}%`, `80%`], center: ['50%', '42%'], startAngle: this.chartOptions.startAngle ? this.chartOptions.startAngle : 0, endAngle: this.chartOptions.endAngle ? this.chartOptions.endAngle : 0, label: { show: false, }, itemStyle: { label: { show: false, }, labelLine: { show: false, }, borderWidth: 0, }, data: [ { value: 3, itemStyle: { // color: this.chartOptions.backgroundColor // ? this.chartOptions.backgroundColor // : this.backgroundColor, color: 'transparent', borderWidth: 0, }, tooltip: { show: false, }, hoverAnimation: false, }, ], }, ] return series }, generateCirclePieOptions() { const options = { legend: { show: false, }, tooltip: { show: true, trigger: 'item', backgroundColor: '#000342', textStyle: { color: '#fff', }, }, xAxis: [ { show: false, }, ], series: this.generateCirclePieSeries(), } return options }, // 生成配置项 generateChartOption() { const circleOptions = this.generateCirclePieOptions() this.defaultOptions = circleOptions const mergedOptions = deepMerge({}, this.defaultOptions) const res = deepMerge( mergedOptions, this.chartOptions.echartOptions || {} ) return res }, // 更新图表 updateChart() { const option = this.generateChartOption() this.chartInstance.setOption(option, true) }, }, mounted() { window.addEventListener('resize', this.handleResize) this.initChart() }, beforeDestroy() { window.removeEventListener('resize', this.handleResize) if (this.chartInstance) { this.chartInstance.dispose() } }, watch: { chartOptions: { deep: true, handler() { this.updateChart() }, }, }, }</script><!-- Add "scoped" attribute to limit CSS to this component only --><style lang="scss" scoped> .container { width: 100%; height: 100%; position: relative; .custom-title { position: absolute; bottom: 24px; left: 32%; text-align: center; font-size: 14px; color: #4778b0; } .custom-subtitle { position: absolute; width: 100%; top: 50%; left: 0; text-align: center; font-size: 12px; color: #fff; } .custom-type { position: absolute; width: 100%; bottom: 2px; left: 0; text-align: center; font-size: 14px; color: #fff; } .custom-percent { position: absolute; width: 100%; top: 30%; left: 0; text-align: center; font-size: 14px; color: #fff; } .custom-total { position: absolute; bottom: 24px; left: 54%; font-size: 14px; color: #c5cb12; } } #charts { width: 100%; height: 100%; margin: 0 auto; }</style>