UNPKG

7.71 kBJavaScriptView Raw
1import React, { Component } from "react";
2
3import { LinearGradient, Line, Text, Defs, Stop } from "react-native-svg";
4
5class AbstractChart extends Component {
6 calcScaler = data => {
7 if (this.props.fromZero) {
8 return Math.max(...data, 0) - Math.min(...data, 0) || 1;
9 } else {
10 return Math.max(...data) - Math.min(...data) || 1;
11 }
12 };
13
14 calcBaseHeight = (data, height) => {
15 const min = Math.min(...data);
16 const max = Math.max(...data);
17 if (min >= 0 && max >= 0) {
18 return height;
19 } else if (min < 0 && max <= 0) {
20 return 0;
21 } else if (min < 0 && max > 0) {
22 return (height * max) / this.calcScaler(data);
23 }
24 };
25
26 calcHeight = (val, data, height) => {
27 const max = Math.max(...data);
28 const min = Math.min(...data);
29 if (min < 0 && max > 0) {
30 return height * (val / this.calcScaler(data));
31 } else if (min >= 0 && max >= 0) {
32 return this.props.fromZero
33 ? height * (val / this.calcScaler(data))
34 : height * ((val - min) / this.calcScaler(data));
35 } else if (min < 0 && max <= 0) {
36 return this.props.fromZero
37 ? height * (val / this.calcScaler(data))
38 : height * ((val - max) / this.calcScaler(data));
39 }
40 };
41
42 getPropsForBackgroundLines() {
43 const { propsForBackgroundLines = {} } = this.props.chartConfig;
44 return {
45 stroke: this.props.chartConfig.color(0.2),
46 strokeDasharray: "5, 10",
47 strokeWidth: 1,
48 ...propsForBackgroundLines
49 };
50 }
51
52 getPropsForLabels() {
53 const {
54 propsForLabels = {},
55 color,
56 labelColor = color
57 } = this.props.chartConfig;
58 return {
59 fontSize: 12,
60 fill: labelColor(0.8),
61 ...propsForLabels
62 };
63 }
64
65 renderHorizontalLines = config => {
66 const { count, width, height, paddingTop, paddingRight } = config;
67 return [...new Array(count)].map((_, i) => {
68 return (
69 <Line
70 key={Math.random()}
71 x1={paddingRight}
72 y1={(height / 4) * i + paddingTop}
73 x2={width}
74 y2={(height / 4) * i + paddingTop}
75 {...this.getPropsForBackgroundLines()}
76 />
77 );
78 });
79 };
80
81 renderHorizontalLine = config => {
82 const { width, height, paddingTop, paddingRight } = config;
83 return (
84 <Line
85 key={Math.random()}
86 x1={paddingRight}
87 y1={height - height / 4 + paddingTop}
88 x2={width}
89 y2={height - height / 4 + paddingTop}
90 {...this.getPropsForBackgroundLines()}
91 />
92 );
93 };
94
95 renderHorizontalLabels = config => {
96 const {
97 count,
98 data,
99 height,
100 paddingTop,
101 paddingRight,
102 horizontalLabelRotation = 0,
103 formatYLabel = yLabel => yLabel
104 } = config;
105 const {
106 yAxisLabel = "",
107 yAxisSuffix = "",
108 yLabelsOffset = 12,
109 chartConfig
110 } = this.props;
111 const { decimalPlaces = 2 } = chartConfig;
112 return [...new Array(count)].map((_, i) => {
113 let yLabel;
114
115 if (count === 1) {
116 yLabel = `${yAxisLabel}${formatYLabel(
117 data[0].toFixed(decimalPlaces)
118 )}${yAxisSuffix}`;
119 } else {
120 const label = this.props.fromZero
121 ? (this.calcScaler(data) / (count - 1)) * i + Math.min(...data, 0)
122 : (this.calcScaler(data) / (count - 1)) * i + Math.min(...data);
123 yLabel = `${yAxisLabel}${formatYLabel(
124 label.toFixed(decimalPlaces)
125 )}${yAxisSuffix}`;
126 }
127
128 const x = paddingRight - yLabelsOffset;
129 const y =
130 count === 1 && this.props.fromZero
131 ? paddingTop + 4
132 : (height * 3) / 4 - ((height - paddingTop) / count) * i + 12;
133 return (
134 <Text
135 rotation={horizontalLabelRotation}
136 origin={`${x}, ${y}`}
137 key={Math.random()}
138 x={x}
139 textAnchor="end"
140 y={y}
141 {...this.getPropsForLabels()}
142 >
143 {yLabel}
144 </Text>
145 );
146 });
147 };
148
149 renderVerticalLabels = config => {
150 const {
151 labels = [],
152 width,
153 height,
154 paddingRight,
155 paddingTop,
156 horizontalOffset = 0,
157 stackedBar = false,
158 verticalLabelRotation = 0,
159 formatXLabel = xLabel => xLabel
160 } = config;
161 const {
162 xAxisLabel = "",
163 xLabelsOffset = 0,
164 hidePointsAtIndex = []
165 } = this.props;
166 const fontSize = 12;
167 let fac = 1;
168 if (stackedBar) {
169 fac = 0.71;
170 }
171 return labels.map((label, i) => {
172 if (hidePointsAtIndex.includes(i)) {
173 return null;
174 }
175 const x =
176 (((width - paddingRight) / labels.length) * i +
177 paddingRight +
178 horizontalOffset) *
179 fac;
180 const y = (height * 3) / 4 + paddingTop + fontSize * 2 + xLabelsOffset;
181 return (
182 <Text
183 origin={`${x}, ${y}`}
184 rotation={verticalLabelRotation}
185 key={Math.random()}
186 x={x}
187 y={y}
188 textAnchor={verticalLabelRotation === 0 ? "middle" : "start"}
189 {...this.getPropsForLabels()}
190 >
191 {`${formatXLabel(label)}${xAxisLabel}`}
192 </Text>
193 );
194 });
195 };
196
197 renderVerticalLines = config => {
198 const { data, width, height, paddingTop, paddingRight } = config;
199 return [...new Array(data.length)].map((_, i) => {
200 return (
201 <Line
202 key={Math.random()}
203 x1={Math.floor(
204 ((width - paddingRight) / data.length) * i + paddingRight
205 )}
206 y1={0}
207 x2={Math.floor(
208 ((width - paddingRight) / data.length) * i + paddingRight
209 )}
210 y2={height - height / 4 + paddingTop}
211 {...this.getPropsForBackgroundLines()}
212 />
213 );
214 });
215 };
216
217 renderVerticalLine = config => {
218 const { height, paddingTop, paddingRight } = config;
219 return (
220 <Line
221 key={Math.random()}
222 x1={Math.floor(paddingRight)}
223 y1={0}
224 x2={Math.floor(paddingRight)}
225 y2={height - height / 4 + paddingTop}
226 {...this.getPropsForBackgroundLines()}
227 />
228 );
229 };
230
231 renderDefs = config => {
232 const {
233 width,
234 height,
235 backgroundGradientFrom,
236 backgroundGradientTo
237 } = config;
238 const fromOpacity = config.hasOwnProperty("backgroundGradientFromOpacity")
239 ? config.backgroundGradientFromOpacity
240 : 1.0;
241 const toOpacity = config.hasOwnProperty("backgroundGradientToOpacity")
242 ? config.backgroundGradientToOpacity
243 : 1.0;
244
245 const fillShadowGradient = config.hasOwnProperty("fillShadowGradient")
246 ? config.fillShadowGradient
247 : this.props.chartConfig.color();
248
249 const fillShadowGradientOpacity = config.hasOwnProperty(
250 "fillShadowGradientOpacity"
251 )
252 ? config.fillShadowGradientOpacity
253 : 0.1;
254
255 return (
256 <Defs>
257 <LinearGradient
258 id="backgroundGradient"
259 x1="0"
260 y1={height}
261 x2={width}
262 y2={0}
263 >
264 <Stop
265 offset="0"
266 stopColor={backgroundGradientFrom}
267 stopOpacity={fromOpacity}
268 />
269 <Stop
270 offset="1"
271 stopColor={backgroundGradientTo}
272 stopOpacity={toOpacity}
273 />
274 </LinearGradient>
275 <LinearGradient
276 id="fillShadowGradient"
277 x1={0}
278 y1={0}
279 x2={0}
280 y2={height}
281 >
282 <Stop
283 offset="0"
284 stopColor={fillShadowGradient}
285 stopOpacity={fillShadowGradientOpacity}
286 />
287 <Stop offset="1" stopColor={fillShadowGradient} stopOpacity="0" />
288 </LinearGradient>
289 </Defs>
290 );
291 };
292}
293
294export default AbstractChart;