echarts实例:进度条加描述
记录下工作中使用echarts做出的特殊组件
![]()
import { defineComponent } from 'vue'
import { FONT_SIZE, COLOR_LIGHT_ORG, COLOR_YELLOW, COLOR_LIGHT_GREEN } from './createChart'
let props = {
propData: {
type: Array,
default: () => [
{ name: '名称1', value: 353, color: COLOR_YELLOW, desc: '{x}条描述' },
{ name: '名称2', value: 85, color: COLOR_LIGHT_GREEN, desc: '{2}条描述' },
{ name: '名称3', value: 30, color: '#FF6B6B', desc: '包括{名称3} XX{2}条描述,XX{4}条描述,XX{2}条描述' },
{ name: '名称4', value: 8, color: '#00BAAE', desc: '' },
],
},
barWidth: {
default: 25,
type: Number,
},
}
const colors = [COLOR_LIGHT_ORG, COLOR_YELLOW, COLOR_LIGHT_GREEN, '#7B68EE', '#FF6B6B', '#4ECDC4'] // 添加更多备用颜色
export default defineComponent({
props,
data() {
return {
fontSize: FONT_SIZE + 4,
}
},
created() {},
mounted() {
this.init()
this.$watch(
() => this.$props, // 监听整个 props 对象
() => {
this.init()
},
{ deep: true, immediate: false },
)
},
beforeDestroy() {
this.chart?.dispose?.()
},
methods: {
init() {
const option = this.getOption() // 间隙
const dom = this.$refs.chart
if (!this.chart) {
this.chart = echarts.init(dom, null, {
renderer: 'canvas',
})
}
this.chart.setOption(option, true)
},
getOption() {
if (!this.propData.length) return {}
const seriesdata = this.getData()
const series = this.getSeries(seriesdata)
const maxValue = this.getMaxValue(this.propData)
const seriesBg = this.getBackgroundBarSeries(maxValue)
return {
legend: {
show: false,
},
tooltip: {
show: false,
},
grid: {
left: '6%',
right: '5%',
bottom: '0%',
top: '1%',
containLabel: true,
},
xAxis: [
{
type: 'value',
axisLine: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
},
],
yAxis: [
{
type: 'category',
data: _.map(this.propData, 'name'),
axisLine: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: true,
fontSize: this.fontSize,
textStyle: {
color: '#fff',
},
align: 'left', // 左对齐
padding: [0, 0, 0, -150], // 去掉内边距
interval: 0,
},
axisTick: {
show: false,
},
},
{
type: 'category',
data: this.propData,
offSet: -10,
axisLine: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
},
{
type: 'category',
data: this.propData,
axisLine: {
show: false,
},
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
axisTick: {
show: false,
},
},
],
series: [...seriesBg, ...series],
}
},
// 获取最大值
getMaxValue(data) {
const values = _.map(data, 'value')
return Math.max(...values)
},
getData() {
return this.propData.map((item, index) => {
const color = item.color || colors[index] || '#ffffff'
return {
...item,
label: {
show: true,
position: [0, 0],
fontSize: this.fontSize - 5,
offset: [20, -70],
color: '#fff',
formatter: (params, index) => {
const text = this.propData[params.dataIndex]?.desc || ''
// 将文本拆分成数组,然后组合成富文本字符串
const parts = text.split(/(\{[^}]+\})/)
let richText = ''
parts.forEach((part) => {
if (part.startsWith('{') && part.endsWith('}')) {
// 移除花括号
const value = part.substring(1, part.length - 1)
richText += `{num|${value}}`
} else if (part) {
richText += part
}
})
return richText
},
rich: {
num: {
color, // 动态颜色
fontSize: this.fontSize ,
padding: [0, 5, 0, 5],
},
},
},
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0, // 上
x2: 1,
y2: 0, // 下
colorStops: [
{
offset: 0,
color: echarts.color.modifyAlpha(color, 0.1),
},
{
offset: 0.3,
color: echarts.color.modifyAlpha(color, 0.6),
},
{
offset: 1,
color: echarts.color.modifyAlpha(color, 1),
},
],
},
shadowColor: 'rgba(255,255,255,0.2)',
shadowBlur: 5,
shadowOffsetX: 0,
shadowOffsetY: 0,
},
}
})
},
getSeries(data) {
return [
{
name: '主系列',
type: 'bar',
stack: 'total',
barWidth: this.barWidth,
yAxisIndex: 0,
z: 2,
data,
},
]
},
// 最大值为背景底部进度条
getBackgroundBarSeries(maxValue) {
const config = {
data: this.propData.map(() => {
return maxValue
}),
tooltip: { show: false },
showInLegend: false,
}
const series = [
{
...config,
type: 'bar',
name: '背景bar',
barWidth: this.barWidth,
itemStyle: {
color: 'rgba(255, 255, 255,0.13)',
borderWidth: 0,
},
yAxisIndex: 1,
},
{
...config,
type: 'bar',
name: '背景框',
data: this.propData.map((i, index) => {
return {
value: maxValue + 5,
label: {
color: this.propData[index]?.color || '#fff',
},
}
}),
barWidth: this.barWidth + 20,
itemStyle: {
color: 'rgba(255, 255, 255,0)',
borderColor: '#fff',
borderWidth: 2,
borderRadius: 0,
},
label: {
show: true,
position: 'right',
fontSize: this.fontSize+10,
fontFamily: 'TRENDS',
offset: [50, 0],
formatter: (params) => {
return this.propData[params.dataIndex]?.value || 0
},
},
yAxisIndex: 2,
},
]
return series
},
},
})