index.js 4.16 KB
Newer Older
niko's avatar
niko committed
1 2
import React, { Component } from 'react';
import { Chart, Tooltip, Geom, Coord, Axis } from 'bizcharts';
3
import { Row, Col } from 'antd';
niko's avatar
niko committed
4
import autoHeight from '../autoHeight';
5 6 7
import styles from './index.less';

/* eslint react/no-danger:0 */
afc163's avatar
afc163 committed
8
export default
niko's avatar
niko committed
9
@autoHeight()
afc163's avatar
afc163 committed
10
class Radar extends Component {
11 12
  state = {
    legendData: [],
niko's avatar
niko committed
13
  };
14 15

  componentDidMount() {
16
    this.getLegendData();
17 18
  }

jim's avatar
jim committed
19
  componentDidUpdate(preProps) {
20
    const { data } = this.props;
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
21
    if (data !== preProps.data) {
jim's avatar
jim committed
22
      this.getLegendData();
23 24 25
    }
  }

jim's avatar
jim committed
26
  getG2Instance = chart => {
niko's avatar
niko committed
27 28 29 30
    this.chart = chart;
  };

  // for custom lengend view
jim's avatar
jim committed
31
  getLegendData = () => {
niko's avatar
niko committed
32 33
    if (!this.chart) return;
    const geom = this.chart.getAllGeoms()[0]; // θŽ·ε–ζ‰€ζœ‰ηš„ε›Ύε½’
wangyun's avatar
wangyun committed
34
    if (!geom) return;
niko's avatar
niko committed
35 36
    const items = geom.get('dataArray') || []; // θŽ·ε–ε›Ύε½’ε―ΉεΊ”ηš„

jim's avatar
jim committed
37
    const legendData = items.map(item => {
niko's avatar
niko committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
      // eslint-disable-next-line
      const origins = item.map(t => t._origin);
      const result = {
        name: origins[0].name,
        color: item[0].color,
        checked: true,
        value: origins.reduce((p, n) => p + n.value, 0),
      };

      return result;
    });

    this.setState({
      legendData,
    });
  };
54

jim's avatar
jim committed
55
  handleRef = n => {
56
    this.node = n;
niko's avatar
niko committed
57
  };
58 59 60 61 62

  handleLegendClick = (item, i) => {
    const newItem = item;
    newItem.checked = !newItem.checked;

afc163's avatar
afc163 committed
63
    const { legendData } = this.state;
64 65
    legendData[i] = newItem;

jim's avatar
jim committed
66
    const filteredLegendData = legendData.filter(l => l.checked).map(l => l.name);
niko's avatar
niko committed
67

68
    if (this.chart) {
niko's avatar
niko committed
69
      this.chart.filter('name', val => filteredLegendData.indexOf(val) > -1);
70 71 72 73 74 75
      this.chart.repaint();
    }

    this.setState({
      legendData,
    });
niko's avatar
niko committed
76
  };
77

niko's avatar
niko committed
78 79 80 81 82 83 84 85 86 87
  render() {
    const defaultColors = [
      '#1890FF',
      '#FACC14',
      '#2FC25B',
      '#8543E0',
      '#F04864',
      '#13C2C2',
      '#fa8c16',
      '#a0d911',
afc163's avatar
afc163 committed
88
    ];
niko's avatar
niko committed
89

niko's avatar
niko committed
90 91 92 93 94 95 96 97 98 99 100
    const {
      data = [],
      height = 0,
      title,
      hasLegend = false,
      forceFit = true,
      tickCount = 4,
      padding = [35, 30, 16, 30],
      animate = true,
      colors = defaultColors,
    } = this.props;
101

niko's avatar
niko committed
102
    const { legendData } = this.state;
103

niko's avatar
niko committed
104
    const scale = {
105 106 107 108
      value: {
        min: 0,
        tickCount,
      },
niko's avatar
niko committed
109
    };
110

niko's avatar
niko committed
111
    const chartHeight = height - (hasLegend ? 80 : 22);
112 113 114

    return (
      <div className={styles.radar} style={{ height }}>
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
        {title && <h4>{title}</h4>}
        <Chart
          scale={scale}
          height={chartHeight}
          forceFit={forceFit}
          data={data}
          padding={padding}
          animate={animate}
          onGetG2Instance={this.getG2Instance}
        >
          <Tooltip />
          <Coord type="polar" />
          <Axis
            name="label"
            line={null}
            tickLine={null}
            grid={{
              lineStyle: {
                lineDash: null,
              },
              hideFirstLine: false,
            }}
          />
          <Axis
            name="value"
            grid={{
              type: 'polygon',
              lineStyle: {
                lineDash: null,
              },
            }}
          />
jim's avatar
jim committed
147
          <Geom type="line" position="label*value" color={['name', colors]} size={1} />
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
          <Geom
            type="point"
            position="label*value"
            color={['name', colors]}
            shape="circle"
            size={3}
          />
        </Chart>
        {hasLegend && (
          <Row className={styles.legend}>
            {legendData.map((item, i) => (
              <Col
                span={24 / legendData.length}
                key={item.name}
                onClick={() => this.handleLegendClick(item, i)}
              >
                <div className={styles.legendItem}>
                  <p>
                    <span
                      className={styles.dot}
                      style={{
                        backgroundColor: !item.checked ? '#aaa' : item.color,
                      }}
                    />
                    <span>{item.name}</span>
                  </p>
                  <h6>{item.value}</h6>
                </div>
              </Col>
jim's avatar
jim committed
177
            ))}
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
178 179
          </Row>
        )}
180 181 182 183
      </div>
    );
  }
}