Skip to content

Commit 6f57ff3

Browse files
authored
Add yRange support again, code linting and bugfixes on android. (#23)
1 parent 3293364 commit 6f57ff3

File tree

7 files changed

+79
-40
lines changed

7 files changed

+79
-40
lines changed

src/charts/linear/ChartDot.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useContext } from 'react';
22
import Animated from 'react-native-reanimated';
3+
34
import ChartContext from '../../helpers/ChartContext';
45
import withReanimatedFallback from '../../helpers/withReanimatedFallback';
56

src/charts/linear/ChartLabels.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Animated, {
44
useAnimatedStyle,
55
useDerivedValue,
66
} from 'react-native-reanimated';
7+
78
import ChartContext from '../../helpers/ChartContext';
89

910
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);

src/charts/linear/ChartPath.js

Lines changed: 74 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import Animated, {
1717
withTiming,
1818
} from 'react-native-reanimated';
1919
import { Path, Svg } from 'react-native-svg';
20+
2021
import ChartContext, {
2122
useGenerateValues as generateValues,
2223
} from '../../helpers/ChartContext';
@@ -64,16 +65,18 @@ function combineConfigs(a, b) {
6465
return r;
6566
}
6667

67-
const parse = data => {
68+
const parse = (data, yRange) => {
6869
const { greatestY, smallestY } = findYExtremes(data);
70+
const minY = yRange ? yRange[0] : smallestY.y;
71+
const maxY = yRange ? yRange[1] : greatestY.y;
6972
const smallestX = data[0];
7073
const greatestX = data[data.length - 1];
7174
return [
7275
data.map(({ x, y }) => ({
7376
originalX: x,
7477
originalY: y,
7578
x: (x - smallestX.x) / (greatestX.x - smallestX.x),
76-
y: 1 - (y - smallestY.y) / (greatestY.y - smallestY.y),
79+
y: 1 - (y - minY) / (maxY - minY),
7780
})),
7881
{
7982
greatestX,
@@ -101,6 +104,13 @@ function setoriginalXYAccordingToPosition(
101104
idx = data.value.length - 1;
102105
}
103106
}
107+
if (!data.value[idx]) {
108+
// prevent the following error on android:
109+
// java.lang.RuntimeException: undefined is not an object (evaluating 'data.value[idx].originalX')
110+
// why data.value = [] sometimes onActive?
111+
console.warn('No data available for chart', data.value.length, idx);
112+
return;
113+
}
104114
originalX.value = data.value[idx].originalX.toString();
105115
originalY.value = data.value[idx].originalY
106116
? data.value[idx].originalY.toString()
@@ -197,20 +207,19 @@ export default function ChartPathProvider({
197207
} else {
198208
setData(providedData);
199209
}
200-
// eslint-disable-next-line react-hooks/exhaustive-deps
201210
}, [providedData]);
202211

203212
const smoothingStrategy = useSharedValue(data.smoothingStrategy);
204213

205214
useEffect(() => {
206-
if (!data || !data.points) {
215+
if (!data || !data.points || data.points.length === 0) {
207216
return;
208217
}
209-
const [parsedData] = parse(data.points);
218+
const [parsedData] = parse(data.points, data.yRange);
210219
const [parsedoriginalData, newExtremes] = parse(
211220
data.nativePoints || data.points
212221
);
213-
setContextValue(prev => ({ ...prev, ...newExtremes, data }));
222+
setContextValue((prev) => ({ ...prev, ...newExtremes, data }));
214223
setExtremes(newExtremes);
215224
if (prevData.value.length !== 0) {
216225
valuesStore.current.prevData = currData.value;
@@ -248,13 +257,12 @@ export default function ChartPathProvider({
248257
currData.value = parsedData;
249258
curroriginalData.value = parsedoriginalData;
250259
}
251-
// eslint-disable-next-line react-hooks/exhaustive-deps
252260
}, [data]);
253261

254262
const isStarted = useSharedValue(false, 'isStarted');
255263

256264
const onLongPressGestureEvent = useAnimatedGestureHandler({
257-
onActive: event => {
265+
onActive: (event) => {
258266
state.value = event.state;
259267
if (!currData.value || currData.value.length === 0) {
260268
return;
@@ -282,7 +290,7 @@ export default function ChartPathProvider({
282290
);
283291

284292
let idx = 0;
285-
let ss = smoothingStrategy;
293+
const ss = smoothingStrategy;
286294
for (let i = 0; i < currData.value.length; i++) {
287295
if (getValue(currData, i, ss).x > eventX / layoutSize.value.width) {
288296
idx = i;
@@ -332,7 +340,7 @@ export default function ChartPathProvider({
332340
);
333341
positionX.value = eventX;
334342
},
335-
onCancel: event => {
343+
onCancel: (event) => {
336344
isStarted.value = false;
337345
state.value = event.state;
338346
originalX.value = '';
@@ -350,7 +358,7 @@ export default function ChartPathProvider({
350358
);
351359
}
352360
},
353-
onEnd: event => {
361+
onEnd: (event) => {
354362
isStarted.value = false;
355363
state.value = event.state;
356364
originalX.value = '';
@@ -372,7 +380,7 @@ export default function ChartPathProvider({
372380
impactHeavy();
373381
}
374382
},
375-
onFail: event => {
383+
onFail: (event) => {
376384
isStarted.value = false;
377385
state.value = event.state;
378386
originalX.value = '';
@@ -390,11 +398,28 @@ export default function ChartPathProvider({
390398
);
391399
}
392400
},
393-
onStart: event => {
401+
onStart: (event) => {
402+
// WARNING: the following code does not run on using iOS, but it does on Android.
403+
// I use the same code from onActive except of "progress.value = 1" which was taken from the original onStart.
394404
state.value = event.state;
395405
if (!currData.value || currData.value.length === 0) {
396406
return;
397407
}
408+
if (!isStarted.value) {
409+
dotScale.value = withSpring(
410+
1,
411+
combineConfigs(springDefaultConfig, springConfig)
412+
);
413+
pathOpacity.value = withTiming(
414+
0,
415+
combineConfigs(timingFeedbackDefaultConfig, timingFeedbackConfig)
416+
);
417+
}
418+
419+
if (hapticsEnabledValue.value && !isStarted.value) {
420+
impactHeavy();
421+
}
422+
isStarted.value = true;
398423

399424
const eventX = positionXWithMargin(
400425
event.x,
@@ -404,46 +429,58 @@ export default function ChartPathProvider({
404429

405430
progress.value = 1;
406431
let idx = 0;
432+
const ss = smoothingStrategy;
407433
for (let i = 0; i < currData.value.length; i++) {
408-
if (currData.value[i].x > eventX / layoutSize.value.width) {
434+
if (getValue(currData, i, ss).x > eventX / layoutSize.value.width) {
409435
idx = i;
410436
break;
411437
}
412438
if (i === currData.value.length - 1) {
413439
idx = currData.value.length - 1;
414440
}
415441
}
442+
443+
if (
444+
ss.value === 'bezier' &&
445+
currData.value.length > 30 &&
446+
eventX / layoutSize.value.width >=
447+
currData.value[currData.value.length - 2].x
448+
) {
449+
const prevLastY = currData.value[currData.value.length - 2].y;
450+
const prevLastX = currData.value[currData.value.length - 2].x;
451+
const lastY = currData.value[currData.value.length - 1].y;
452+
const lastX = currData.value[currData.value.length - 1].x;
453+
const progress =
454+
(eventX / layoutSize.value.width - prevLastX) / (lastX - prevLastX);
455+
positionY.value =
456+
(prevLastY + progress * (lastY - prevLastY)) *
457+
layoutSize.value.height;
458+
} else if (idx === 0) {
459+
positionY.value =
460+
getValue(currData, idx, ss).y * layoutSize.value.height;
461+
} else {
462+
// prev + diff over X
463+
positionY.value =
464+
(getValue(currData, idx - 1, ss).y +
465+
(getValue(currData, idx, ss).y -
466+
getValue(currData, idx - 1, ss).y) *
467+
((eventX / layoutSize.value.width -
468+
getValue(currData, idx - 1, ss).x) /
469+
(getValue(currData, idx, ss).x -
470+
getValue(currData, idx - 1, ss).x))) *
471+
layoutSize.value.height;
472+
}
473+
416474
setoriginalXYAccordingToPosition(
417475
originalX,
418476
originalY,
419477
eventX / layoutSize.value.width,
420478
curroriginalData
421479
);
422-
dotScale.value = withSpring(
423-
1,
424-
combineConfigs(springDefaultConfig, springConfig)
425-
);
426-
427-
if (!android) {
428-
positionX.value = positionXWithMargin(
429-
eventX,
430-
30,
431-
layoutSize.value.width
432-
);
433-
positionY.value = currData.value[idx].y * layoutSize.value.height;
434-
pathOpacity.value = withTiming(
435-
0,
436-
combineConfigs(timingFeedbackDefaultConfig, timingFeedbackConfig)
437-
);
438-
}
439-
if (hapticsEnabledValue.value && !isStarted.value) {
440-
impactHeavy();
441-
}
442-
isStarted.value = true;
480+
positionX.value = eventX;
443481
},
444482
});
445483

446-
// @ts-ignore
447484
const dotStyle = useAnimatedStyle(
448485
() => ({
449486
opacity: dotScale.value,
@@ -521,7 +558,7 @@ function ChartPath({
521558
let toValue = currData.value;
522559
let res;
523560
let smoothing = 0;
524-
let strategy = smoothingStrategy.value;
561+
const strategy = smoothingStrategy.value;
525562
if (progress.value !== 1) {
526563
const numOfPoints = Math.round(
527564
fromValue.length +

src/charts/linear/ChartPathProvider.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useMemo, useState } from 'react';
22
import { useAnimatedStyle } from 'react-native-reanimated';
3+
34
import ChartContext, { useGenerateValues } from '../../helpers/ChartContext';
45

56
export default function ChartPathProvider({ data: providedData, children }) {

src/helpers/useReactiveSharedValue.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { useEffect } from 'react';
2-
// eslint-disable-next-line import/no-unresolved
32
import { useSharedValue } from 'react-native-reanimated';
43

54
export default function useReactiveSharedValue(prop, name) {

src/helpers/withReanimatedFallback.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react';
22
import { Text, TurboModuleRegistry } from 'react-native';
33

44
function ChartFallback() {
5-
return <Text> Charts are not available without Reanimated 2</Text>;
5+
return <Text>Charts are not available without Reanimated 2</Text>;
66
}
77

88
export default function withReanimatedFallback(

src/interpolations/bSplineInterpolation.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class BSpline {
3030
seqAt(dim) {
3131
let points = this.points;
3232
let margin = this.degree + 1;
33-
return function (n) {
33+
return function(n) {
3434
if (n < margin) {
3535
return points[0][dim];
3636
} else if (points.length + margin <= n) {

0 commit comments

Comments
 (0)