index.js 2.22 KB
import React, { PureComponent } from 'react';
import { Chart } from '@antv/g2';
import debounce from 'lodash/debounce';

const primaryColor = '#2F9CFF';
const backgroundColor = '#F0F2F5';

class Gauge extends PureComponent {
  componentDidMount() {
    this.renderChart();
    window.addEventListener('resize', this.resize);
  }

  componentWillReceiveProps(nextProps) {
    if (!this.isEqual(this.props, nextProps)) {
      this.renderChart(nextProps);
    }
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.resize);
    this.resize.cancel();
    if (this.chart) {
      this.chart.destroy();
    }
  }

  resize = debounce(() => {
    if (this.chart) {
      this.chart.render();
    }
  }, 200);

  isEqual = (prevProps, nextProps) => {
    // Implement your own equality check logic
    return prevProps.data === nextProps.data && prevProps.color === nextProps.color;
  };

  renderChart = (props = this.props) => {
    const { data, color = primaryColor, bgColor = backgroundColor } = props;
    const value = Math.min(Math.max(data, 0), 100); // Ensure value is between 0 and 100

    if (this.chart) {
      this.chart.destroy();
    }

    const chart = new Chart({
      container: this.node,
      autoFit: true,
      height: 200,
      padding: [20, 20, 60, 20],
    });

    chart.tooltip(false);

    chart.coordinate('polar', {
      startAngle: -Math.PI / 2,
      endAngle: Math.PI / 2,
      radius: 0.9,
    });

    chart.axis('value', false);

    // Draw background arc
    chart.guide().arc({
      start: [0, 0.95],
      end: [100, 0.95],
      style: {
        stroke: bgColor,
        lineWidth: 12,
      },
    });

    // Draw value arc
    chart.guide().arc({
      start: [0, 0.95],
      end: [value, 0.95],
      style: {
        stroke: color,
        lineWidth: 12,
      },
    });

    // Draw center circle
    chart.guide().html({
      position: [50, 0.95],
      html: `<div style="text-align: center; font-size: 12px; color: rgba(0, 0, 0, 0.43); transform: translate(-50%, -50%);">${value}%</div>`,
    });

    chart.render();

    this.chart = chart;
  };

  handleRef = (node) => {
    this.node = node;
  };

  render() {
    return <div ref={this.handleRef}></div>;
  }
}

export default Gauge;