1 | import React, {
|
2 | PropTypes,
|
3 | Component,
|
4 | } from 'react';
|
5 | import {
|
6 | View,
|
7 | Text,
|
8 | StyleSheet,
|
9 | } from 'react-native';
|
10 | import AxisX from './AxisX';
|
11 | import AxisXContainer from './AxisXContainer';
|
12 | import Rectangular from './Rectangular';
|
13 | import ShapContainer from './ShapContainer';
|
14 | import TopPoint from './TopPoint';
|
15 |
|
16 | const styles = StyleSheet.create({
|
17 | yAxis: {
|
18 | flex: 1,
|
19 | flexDirection: 'column',
|
20 | justifyContent: 'space-between',
|
21 | alignItems: 'flex-end',
|
22 | },
|
23 | textColor: {
|
24 | color: '#DCDEE5',
|
25 | },
|
26 | bdWrap: {
|
27 | flex: 1,
|
28 | alignItems: 'center',
|
29 | },
|
30 | topValBar: {
|
31 | flex: 1,
|
32 | flexDirection: 'row',
|
33 | justifyContent: 'space-around',
|
34 | },
|
35 | });
|
36 |
|
37 | class BarChart extends Component {
|
38 | static propTypes = {
|
39 | customStyle: PropTypes.shape({
|
40 | width: PropTypes.number.isRequired,
|
41 | height: PropTypes.number.isRequired,
|
42 | fillColor: PropTypes.string.isRequired,
|
43 | backgroundColor: PropTypes.string.isRequired,
|
44 | raduis: PropTypes.number.isRequired,
|
45 | parity: PropTypes.string.isRequired,
|
46 | piecewise: PropTypes.number.isRequired,
|
47 | topAxisXShow: PropTypes.bool.isRequired,
|
48 | showAxisY: PropTypes.bool.isRequired,
|
49 | showAxisXLine: PropTypes.bool.isRequired,
|
50 | showTopBar: PropTypes.bool.isRequired,
|
51 | borderColor: PropTypes.string.isRequired,
|
52 | textStyle: PropTypes.object.isRequired,
|
53 | topTextStyle: PropTypes.object.isRequired,
|
54 | onClick: PropTypes.func,
|
55 | unitName: PropTypes.string,
|
56 | xAxisContainerStyle: PropTypes.object,
|
57 | }),
|
58 | dataSource: PropTypes.array,
|
59 | }
|
60 | static defaultProps = {
|
61 | customStyle: {},
|
62 | dataSource: [],
|
63 | }
|
64 | constructor(props) {
|
65 | super(props);
|
66 | this.AxisX = [];
|
67 | this.AxisY = [];
|
68 | this.ChartArea = [];
|
69 | this.TopValBar = [];
|
70 | this.createChart(this.props.dataSource);
|
71 | }
|
72 | componentWillUpdate(nextProps) {
|
73 | this.createChart(nextProps.dataSource);
|
74 | }
|
75 | _findMaxVal(data) {
|
76 | let max = Math.max(...data);
|
77 | const average = this._average(max);
|
78 | const piecewise = this.props.customStyle.piecewise;
|
79 | max = piecewise * average;
|
80 | return max;
|
81 | }
|
82 | _average(max) {
|
83 | const piecewise = this.props.customStyle.piecewise;
|
84 | return Math.ceil(max / piecewise);
|
85 | }
|
86 | createLabel(parity, label, idx) {
|
87 | let text;
|
88 | const unitName = this.props.customStyle.unitName;
|
89 | switch (parity) {
|
90 | case 'odd': text = idx % 2 === 0 ? `${label}${unitName}` : '';
|
91 | break;
|
92 | case 'even': text = idx % 2 === 0 ? '' : `${label}${unitName}`;
|
93 | break;
|
94 | default: text = label;
|
95 | break;
|
96 | }
|
97 | return text;
|
98 | }
|
99 | createChart(dataSource) {
|
100 | const ValueList = [];
|
101 | this.AxisX = [];
|
102 | dataSource.forEach((data, idx) => {
|
103 | this.AxisX.push(this.createAxisX(data.x, idx));
|
104 | ValueList.push(data.value);
|
105 | });
|
106 | this.createAxisY(ValueList);
|
107 | this.createChartArea(ValueList, dataSource);
|
108 | }
|
109 | createAxisX(label, idx) {
|
110 | const customStyle = this.props.customStyle;
|
111 | const parity = customStyle.parity;
|
112 | const showAxisXLine = customStyle.showAxisXLine;
|
113 | const text = this.createLabel(parity, label, idx);
|
114 | const style = {
|
115 | fontSize: customStyle.textStyle.fontSize,
|
116 | color: customStyle.textStyle.color,
|
117 | borderColor: customStyle.borderColor,
|
118 | };
|
119 | return <AxisX label={String(text)} key={idx} showAxisXLine={showAxisXLine} style={style} />;
|
120 | }
|
121 |
|
122 | createAxisY(ValueList) {
|
123 | let idx = 0;
|
124 | const max = this._findMaxVal(ValueList);
|
125 | const average = this._average(max);
|
126 | const customStyle = this.props.customStyle;
|
127 | const { textStyle, piecewise } = customStyle;
|
128 |
|
129 | if (max === 0) {
|
130 | return this.AxisY[idx] = <Text style={[styles.textColor, textStyle]} key={99}>{max}</Text>;
|
131 | }
|
132 | for (let i = piecewise; i > -1; i--) {
|
133 | const yLabel = i * average;
|
134 | this.AxisY[idx] = <Text style={[styles.textColor, textStyle]} key={i}>{yLabel}</Text>;
|
135 | idx++;
|
136 | }
|
137 | return null;
|
138 | }
|
139 | createChartArea(ValueList, dataSource) {
|
140 | const { customStyle } = this.props;
|
141 | const max = this._findMaxVal(ValueList);
|
142 | const topTextStyle = customStyle.topTextStyle;
|
143 | const onClick = customStyle.onClick;
|
144 | this.ChartArea = [];
|
145 | this.TopValBar = [];
|
146 | ValueList.map((data, index) => {
|
147 | const value = (data / max) * customStyle.height;
|
148 | customStyle.topAxisXShow ? this.TopValBar.push(<TopPoint key={`${index}`} label={data} style={topTextStyle} />) : null;
|
149 | this.ChartArea.push(<Rectangular onClick={onClick} item={dataSource[index]} key={`li_${index}`} valueHeight={value} customStyle={customStyle} />);
|
150 | return false;
|
151 | });
|
152 | }
|
153 |
|
154 | render() {
|
155 | const customStyle = this.props.customStyle;
|
156 | const axisYWidth = customStyle.axisYWidth;
|
157 | const isBorderRight = customStyle.showAxisY ? { width: axisYWidth - 1, borderRightWidth: 1, borderColor: customStyle.borderColor } : { borderRightWidth: 0, width: 0 };
|
158 | const yAxis = customStyle.showAxisY ? this.AxisY : null;
|
159 | const dynamicStyle = customStyle.showAxisY ? { marginLeft: axisYWidth } : { marginLeft: 0 };
|
160 | const topBar = customStyle.showTopBar ? this.TopValBar : null;
|
161 | const shapStyle = {
|
162 | height: customStyle.height,
|
163 | borderColor: customStyle.borderColor,
|
164 | };
|
165 | return (
|
166 | <View>
|
167 | <View style={dynamicStyle}><View style={styles.topValBar}>{topBar}</View></View>
|
168 | <View style={{ flex: 1, flexDirection: 'row' }}>
|
169 | <View style={isBorderRight}>
|
170 | <View style={[styles.yAxis, { height: customStyle.height }, isBorderRight]}>{yAxis}</View>
|
171 | </View>
|
172 | <View style={{ flex: 1 }}>
|
173 | <View>
|
174 | <ShapContainer style={shapStyle}>{this.ChartArea}</ShapContainer>
|
175 | </View>
|
176 | </View>
|
177 | </View>
|
178 | <View style={[dynamicStyle]}>
|
179 | <AxisXContainer style={customStyle.xAxisContainerStyle}>{this.AxisX}</AxisXContainer>
|
180 | </View>
|
181 | </View>
|
182 | );
|
183 | }
|
184 | }
|
185 | export default BarChart;
|