<template>
<DvChart class="my-dv-ring" :options="optionsFunc" v-bind="{...$props,...$attrs}"></DvChart>
</template>
<script>
/**
* 圆环图
* @module $ui/dv/my-dv-ring
*/
import 'echarts/lib/chart/pie'
import DvChart from '../my-dv-chart'
import Chart from '../../mixins/Chart'
import {DEFAULT_THEME} from '$ui/charts/utils/constant'
export default {
name: 'MyDvRing',
mixins: [Chart],
components: {
DvChart
},
/**
* 属性参数
* @member props
* @property {Array} [columns] 数据列
* @property {Array} [rows] 数据行
* @property {Function} [loader] 数据加载函数,必须返回Promise
* @property {Object} [settings] 图表的私有设置
* @property {Object|Function} [extend] 扩展图表参数选项
* @property {boolean} [debug] 开启打印调试信息
* @property {boolean} [legend] 显示图例, 可选值:'v', 'h', false
* @property {boolean} [label] 显示标签
* @property {number} [radius=45] 半径,取值 0 ~ 100
* @property {string} [title] 标题文本,在圆中心
* @property {boolean} [useGap] 使用间隔
* @property {boolean} [blur] 是否用光斑渐变 默认false
* @property {number} [trackWidth] 圆环宽度
*/
props: {
label: Boolean,
legend: {
type: [String, Boolean],
default: false,
validator(val) {
return ['v', 'h', false].includes(val)
}
},
radius: {
type: Number,
default: 45
},
title: String,
useGap: {
type: Boolean,
default: false
},
blur: {
type: Boolean,
default: false
},
trackWidth: {
type: Number,
default: 15,
validator: function (t) {
return Math.min(5, Math.max(t, 15))
}
}
},
computed: {
seriesData() {
const {rows = []} = this.chartData
const data = rows.map(([name, value], index) => {
let blurOpts = {}
if (this.blur) {
const extColors = this.extend && this.extend.color || [] // 以extend 颜色为优先
const defColors = DEFAULT_THEME.color || [] // 其次以默认主题颜色
const color = 'rgba(255, 255, 255, .6)' // 最后为透明白色
console.log(extColors, defColors, 'ccccc')
blurOpts = {
itemStyle: {
normal: {
shadowBlur: 15,
shadowColor: extColors[index] || defColors[index] || color
}
}
}
console.log(blurOpts, 'dddddd')
}
return {
name,
value,
...blurOpts
}
})
if (this.useGap) {
const total = rows.reduce((total, item) => {
total += item[1]
return total
}, 0)
const gapNum = (total * 0.02).toFixed(1)
return data.reduce((total, item) => {
total = total.concat([item, {
name: '',
value: gapNum,
itemStyle: {
normal: {
borderColor: 'rgba(0, 0, 0, 0)',
borderWidth: 0,
color: 'rgba(0, 0, 0, 0)',
label: { show: false },
labelLine: { show: false }
}
}
}])
return total
}, [])
} else {
return data
}
}
},
methods: {
optionsFunc() {
const isV = this.legend === 'v'
const fontSize = 20
const center = ['50%', '50%']
const radius = this.radius
return {
title: {
text: this.title,
x: 'center',
y: 'center',
textStyle: {
fontSize,
lineHeight: fontSize * 1.2
}
},
legend: {
show: !!this.legend,
top: isV ? 'center' : 20,
left: isV ? undefined : 'center',
right: isV ? 20 : undefined,
itemWidth: 10,
itemHeight: 10,
icon: 'rect',
align: 'auto',
orient: isV ? 'vertical' : 'horizontal'
},
tooltip: {
trigger: 'item',
borderColor: 'rgba(255,255,255,.2)',
backgroundColor: 'rgba(13,5,30,.85)',
borderWidth: 1,
padding: 5,
formatter: function (params) {
const str = params.marker + '' + params.data.name + '</br>' +
'数量:' + params.data.value + '</br>' +
'占比:' + params.percent + '%';
return str;
}
},
series: [
{
type: 'pie',
data: this.seriesData,
z: 3,
center: center,
radius: [`${radius - this.trackWidth}%`, `${radius}%`],
clockwise: true,
avoidLabelOverlap: true,
hoverOffset: 15,
label: {
show: this.label,
position: 'outside',
formatter: '{a|{b}:{d}%}\n{hr|}',
rich: {
hr: {
backgroundColor: 't',
borderRadius: 3,
width: 3,
height: 3,
padding: [3, 3, 0, -12]
},
a: {
padding: [-30, 15, -20, 15]
}
}
},
labelLine: {
normal: {
length: 20,
length2: 15,
lineStyle: {
width: 1
}
}
}
},
{
name: '第一层环',
type: 'pie',
z: 2,
tooltip: {
show: false
},
center: center,
radius: [`${radius}%`, `${radius + 15}%`],
hoverAnimation: false,
clockWise: false,
itemStyle: {
normal: {
shadowBlur: 1,
shadowColor: 'rgba(255,255,255,.2)',
color: 'rgba(1,15,80,.3)'
},
emphasis: {
color: 'rgba(1,15,80,.3)'
}
},
label: {
show: false
},
data: [100]
},
{
name: '第二层环',
type: 'pie',
z: 1,
tooltip: {
show: false
},
center: center,
radius: [`${radius + 15}%`, `${radius + 30}%`],
hoverAnimation: false,
clockWise: false,
itemStyle: {
normal: {
shadowBlur: 1,
shadowColor: 'rgba(255,255,255,.1)',
color: 'rgba(0,15,69,.2)'
},
emphasis: {
color: 'rgba(0,15,69,.2)'
}
},
label: {
show: false
},
data: [100]
}
]
}
}
}
}
</script>