UNPKG

6.35 kBJavaScriptView Raw
1import React, {
2 PropTypes,
3 Component,
4} from 'react';
5import {
6 View,
7 Text,
8 StyleSheet,
9} from 'react-native';
10import AxisX from './AxisX';
11import AxisXContainer from './AxisXContainer';
12import Rectangular from './Rectangular';
13import ShapContainer from './ShapContainer';
14import TopPoint from './TopPoint';
15
16const 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
37class 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, // odd奇数显示 even偶数显示 all显示全部
46 piecewise: PropTypes.number.isRequired, // Y轴度量分几段
47 topAxisXShow: PropTypes.bool.isRequired, // 是否展示顶部对应的value值
48 showAxisY: PropTypes.bool.isRequired, // 是否展示Y轴
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, // click回调
55 unitName: PropTypes.string,
56 xAxisContainerStyle: PropTypes.object, // X轴容器样式
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}
185export default BarChart;