react封装echarts仪表盘
1、仪表盘组件
GaugeChart/index.tsx(组件中的nightFlag是适配黑夜模式,获取公共状态中的值)
import React, { useEffect, useRef } from 'react'
import styles from './index.less'
import { connect } from 'umi'
import { ConnectState } from '@/models/connect'
// echarts
import * as echarts from 'echarts/lib/echarts'
import 'echarts/lib/chart/gauge'
interface GaugeProps {
name: string // 仪表盘名称
unit: string // 单位
target?: number // 目标值
sprint?: number // 冲刺值
current?: number // 当前值
nightFlag?: boolean // 是否开了黑夜模式
}
const GaugeChart: React.FC<GaugeProps> = (props) => {
let chartInstance: any = null // 图表实例
const chartRef = useRef(null)
const { name, unit, target = 0, sprint = 0, current = 0, nightFlag } = props
const hasTargetAndSprint = !!(target && sprint) // 是否有目标值和冲刺值
const max = (sprint: number, target: number, current: number) => {
if (sprint) return Math.ceil(sprint / 5) * 5
if (target) return Math.ceil(target / 5) * 5
if (current) return Math.ceil(current / 5) * 5
return 100
}
const option = {
series: [
{
type: 'gauge',
max: max(sprint, target, current), // 最大值的优先级顺序:冲刺值 任务值 当前值 100
axisLine: {
roundCap: true,
lineStyle: {
width: 10,
color: hasTargetAndSprint
? [
[target / max(sprint, target, current), '#416EFF'],
[1, '#FF6565']
]
: [[1, '#416EFF']]
}
},
anchor: {
show: true,
showAbove: true,
size: 12,
itemStyle: {
color: '#fff',
borderColor: current > target && hasTargetAndSprint ? '#FF6565' : '#416EFF',
borderWidth: 1
}
}, // 空心圆圈
pointer: { width: 5, length: '55%', offsetCenter: [0, -5], itemStyle: { color: 'auto' } }, // 指针
axisTick: { distance: 10, length: 8, lineStyle: { color: 'auto', width: 2 } }, // 虚线
splitLine: { lineStyle: { width: 0 } }, // 当前值 虚线 的宽度
axisLabel: { color: 'inherit', distance: 20, fontSize: 10 }, // 进度数字 0 10 20 30 40 50 60...
detail: { valueAnimation: true, color: 'inherit', fontSize: 30, offsetCenter: [0, '70%'] }, // 当前值
data: [
{
value: current,
name: name,
title: {
fontSize: '16',
color: nightFlag ? '#fff' : '#373A44',
offsetCenter: [0, '90%']
}
}
]
}
]
}
// 初始化
const initChart = () => {
const renderedInstance = echarts.getInstanceByDom(chartRef.current)
if (renderedInstance) {
chartInstance = renderedInstance
} else {
chartInstance = echarts.init(chartRef.current)
}
chartInstance.setOption(option)
}
useEffect(() => {
initChart()
return () => {
chartInstance && chartInstance.dispose()
}
}, [nightFlag])
return (
<div className={styles.gaugeChartContainer}>
<div
style={
hasTargetAndSprint
? { width: '500px', height: '400px' }
: { width: '500px', height: '400px', opacity: 0.8 }
}
ref={chartRef}
></div>
{/* {hasTargetAndSprint ? ( */}
<ul className={styles.legend}>
<li>
<i></i>任务指标:{target}
{unit}
</li>
<li>
<i></i>冲刺指标:{sprint}
{unit}
</li>
</ul>
{/* ) : null} */}
</div>
)
}
// export default GaugeChart
export default connect(({ night: { nightFlag } }: ConnectState) => ({ nightFlag }))(GaugeChart)
GaugeChart/index.less
.gaugeChartContainer { position: relative; margin-bottom: 20px; ul.legend { position: absolute; bottom: 20px; display: flex; justify-content: space-around; width: 100%; margin-bottom: 0; padding-left: 0; li { display: flex; align-items: center; color: var(--theme-text-color); font-size: 14px; i { display: block; width: 20px; height: 12px; margin-right: 8px; background-image: linear-gradient(90deg, #6489ff 0%, #416eff 100%); } &:last-of-type i { background-image: linear-gradient(90deg, #ff926d 0%, #ff6565 100%); } } } }
2、使用
gaugeOptions是一个数组(数据结构中label和value是提供给下拉框组件使用的,仪表盘组件中不需要)
[ { "label": "销售额", "value": 0, "name": "销售额(万元)", "unit": "万元", "target": 49.000066, "sprint": 100, "current": "82.6" }, { "label": "实收款", "value": 1, "name": "实收款(万元)", "unit": "万元", "target": 0, "sprint": 0, "current": "82.9" }, { "label": "新拓客户", "value": 2, "name": "新拓客户(个)", "unit": "个", "target": 51, "sprint": 200, "current": 0 }, { "label": "续签客户", "value": 3, "name": "续签客户(个)", "unit": "个", "target": 55, "sprint": 300, "current": 0 }, { "label": "至尊占比", "value": 4, "name": "至尊占比(%)", "unit": "%", "target": 10000, "sprint": 0, "current": 35.45 }, { "label": "普及率", "value": 5, "name": "普及率(%)", "unit": "%", "target": 45, "sprint": 120, "current": 25.03 } ]
DOM
{gaugeOptions.map((item) => (
<GaugeChart
key={item.value}
unit={item.unit}
name={item.name}
target={item.target}
sprint={item.sprint}
current={item.current}
/>
))}
3、效果


浙公网安备 33010602011771号