1. 程式人生 > 其它 >react封裝echarts儀表盤

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%);
      }
    }
  }
}
View Code

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、效果