Skip to content

Commit ac12f01

Browse files
committed
feat: introduce multiline chart
Key Highlights: - Major API refactor to support multiline charts
1 parent 6d9c871 commit ac12f01

22 files changed

+790
-13
lines changed

example/app/_layout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export default () => (
1010
<Stack>
1111
<Stack.Screen name="index" />
1212
<Stack.Screen name="chart" />
13+
<Stack.Screen name="multi_line_chart" />
1314
</Stack>
1415
</GestureHandlerRootView>
1516
);

example/app/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ export default () => {
1616
<Pressable onPress={() => navigate("/static_chart")}>
1717
<Text style={styles.link}>Go to static chart</Text>
1818
</Pressable>
19+
<Pressable onPress={() => navigate("/multi_line_chart")}>
20+
<Text style={styles.link}>Go to multi line chart</Text>
21+
</Pressable>
1922
</ScrollView>
2023
);
2124
};

example/app/multi_line_chart.tsx

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { Line, MultiLineChart } from "@codeherence/react-native-graph";
2+
import { Circle, Group } from "@shopify/react-native-skia";
3+
import * as Haptics from "expo-haptics";
4+
import { ScrollView, StyleSheet } from "react-native";
5+
import { runOnJS, useDerivedValue, useSharedValue, withTiming } from "react-native-reanimated";
6+
import { useSafeAreaInsets } from "react-native-safe-area-context";
7+
8+
import { priceMap } from "../src/store/prices";
9+
10+
const gestureStartImpact = () => {
11+
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
12+
};
13+
14+
export default () => {
15+
const cursorShown = useSharedValue(false);
16+
const x = useSharedValue(0);
17+
const y = useSharedValue(0);
18+
const { bottom, left, right } = useSafeAreaInsets();
19+
20+
const opacity = useDerivedValue(() => {
21+
// return cursorShown.value ? 1 : 0;
22+
// Use a timing function to animate the opacity
23+
return withTiming(cursorShown.value ? 1 : 0, { duration: 200 });
24+
});
25+
26+
return (
27+
<ScrollView
28+
style={styles.container}
29+
contentContainerStyle={[
30+
styles.contentContainer,
31+
{
32+
paddingBottom: bottom,
33+
paddingLeft: left,
34+
paddingRight: right,
35+
},
36+
]}
37+
showsVerticalScrollIndicator={false}
38+
>
39+
<MultiLineChart
40+
isStatic={false}
41+
points={priceMap}
42+
style={styles.chart}
43+
// ExtraCanvasElements={
44+
// <>
45+
// <Group color="blue" opacity={opacity}>
46+
// <Circle cx={x} cy={y} r={10} />
47+
// </Group>
48+
// </>
49+
// }
50+
onPanGestureBegin={(payload) => {
51+
"worklet";
52+
cursorShown.value = true;
53+
x.value = payload.event.x;
54+
y.value = payload.event.y;
55+
runOnJS(gestureStartImpact)();
56+
}}
57+
onPanGestureEnd={() => {
58+
"worklet";
59+
cursorShown.value = false;
60+
}}
61+
onPanGestureChange={(payload) => {
62+
"worklet";
63+
x.value = payload.event.x;
64+
y.value = payload.event.y;
65+
}}
66+
>
67+
{(args) => (
68+
<>
69+
<Line points={args.points.aapl} strokeWidth={1} color="green" />
70+
<Line points={args.points.msft} strokeWidth={1} color="purple" />
71+
<Line points={args.points.nvda} strokeWidth={1} color="black" />
72+
<Line points={args.points.unity} strokeWidth={1} color="orange" />
73+
</>
74+
)}
75+
</MultiLineChart>
76+
</ScrollView>
77+
);
78+
};
79+
80+
const styles = StyleSheet.create({
81+
container: { flex: 1 },
82+
contentContainer: { flexGrow: 1 },
83+
chart: { flex: 1, maxHeight: 200 },
84+
price: { fontSize: 32 },
85+
buttonContainer: {
86+
flexDirection: "row",
87+
justifyContent: "center",
88+
paddingVertical: 12,
89+
},
90+
toggleBtn: {
91+
padding: 12,
92+
backgroundColor: "blue",
93+
borderRadius: 12,
94+
},
95+
buttonText: {
96+
color: "white",
97+
fontSize: 16,
98+
},
99+
});

example/assets/circle-pic.png

-59.8 KB
Binary file not shown.

example/assets/planets.jpeg

-75.9 KB
Binary file not shown.

example/assets/twitter-verified.svg

Lines changed: 0 additions & 6 deletions
This file was deleted.

example/ios/Podfile.lock

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ PODS:
8383
- ExpoModulesCore
8484
- ExpoFileSystem (16.0.7):
8585
- ExpoModulesCore
86+
- ExpoHaptics (12.8.1):
87+
- ExpoModulesCore
8688
- ExpoHead (3.4.8):
8789
- ExpoModulesCore
8890
- ExpoImage (1.10.6):
@@ -1231,6 +1233,7 @@ DEPENDENCIES:
12311233
- ExpoBlur (from `../node_modules/expo-blur/ios`)
12321234
- ExpoCrypto (from `../node_modules/expo-crypto/ios`)
12331235
- ExpoFileSystem (from `../node_modules/expo-file-system/ios`)
1236+
- ExpoHaptics (from `../node_modules/expo-haptics/ios`)
12341237
- ExpoHead (from `../node_modules/expo-router/ios`)
12351238
- ExpoImage (from `../node_modules/expo-image/ios`)
12361239
- ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`)
@@ -1336,6 +1339,8 @@ EXTERNAL SOURCES:
13361339
:path: "../node_modules/expo-crypto/ios"
13371340
ExpoFileSystem:
13381341
:path: "../node_modules/expo-file-system/ios"
1342+
ExpoHaptics:
1343+
:path: "../node_modules/expo-haptics/ios"
13391344
ExpoHead:
13401345
:path: "../node_modules/expo-router/ios"
13411346
ExpoImage:
@@ -1469,6 +1474,7 @@ SPEC CHECKSUMS:
14691474
ExpoBlur: e832d874bd94afc0645daddbd3162ec1ce172080
14701475
ExpoCrypto: b6428f48599c007676dc81a9b5f72c07e62fdccc
14711476
ExpoFileSystem: c7488590959bf85ebc114909eb8186cbd62e3a25
1477+
ExpoHaptics: 28a771b630353cd6e8dcf1b1e3e693e38ad7c3c3
14721478
ExpoHead: 8224345e80abcf4c97b31c99805dd5a3c8d3404d
14731479
ExpoImage: 8cf2d51de3d03b7e984e9b0ba8f19c0c22057001
14741480
ExpoKeepAwake: 0f5cad99603a3268e50af9a6eb8b76d0d9ac956c

example/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"expo-constants": "~15.4.5",
1818
"expo-crypto": "~12.8.1",
1919
"expo-dev-client": "~3.3.9",
20+
"expo-haptics": "~12.8.1",
2021
"expo-image": "~1.10.6",
2122
"expo-linking": "~6.2.2",
2223
"expo-router": "~3.4.8",

example/yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5189,6 +5189,11 @@ expo-font@~11.10.3:
51895189
dependencies:
51905190
fontfaceobserver "^2.1.0"
51915191

5192+
expo-haptics@~12.8.1:
5193+
version "12.8.1"
5194+
resolved "https://registry.yarnpkg.com/expo-haptics/-/expo-haptics-12.8.1.tgz#42b996763be33d661bd33bbc3b3958c3f2734b9d"
5195+
integrity sha512-ntLsHkfle8K8w9MW8pZEw92ZN3sguaGUSSIxv30fPKNeQFu7Cq/h47Qv3tONv2MO3wU48N9FbKnant6XlfptpA==
5196+
51925197
expo-image@~1.10.6:
51935198
version "1.10.6"
51945199
resolved "https://registry.yarnpkg.com/expo-image/-/expo-image-1.10.6.tgz#b0e54d31d97742505296c076a5f18d094ba9a8cc"

src/components/LineChart/InteractiveLineChart.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import { Cursor } from "./Cursor";
99
import { LineChartProps } from "./LineChart";
1010
import { computePath, computeGraphData } from "./computations";
1111
import { useGestures } from "./useGestures";
12-
import { batchedUpdates } from "../../libs/batchedUpdates";
1312

1413
export const InteractiveLineChart: React.FC<LineChartProps<false>> = ({
1514
points = [],
@@ -33,8 +32,7 @@ export const InteractiveLineChart: React.FC<LineChartProps<false>> = ({
3332
onHoverGestureEnd = null,
3433
...viewProps
3534
}) => {
36-
const [width, setWidth] = useState(0);
37-
const [height, setHeight] = useState(0);
35+
const [{ width, height }, setSize] = useState({ width: 0, height: 0 });
3836

3937
// Initially -cursorRadius so that the cursor is hidden
4038
const x = useSharedValue(-cursorRadius);
@@ -67,10 +65,7 @@ export const InteractiveLineChart: React.FC<LineChartProps<false>> = ({
6765

6866
const onLayout = useCallback((e: LayoutChangeEvent) => {
6967
// Batch the updates to avoid unnecessary re-renders
70-
batchedUpdates(() => {
71-
setWidth(e.nativeEvent.layout.width);
72-
setHeight(e.nativeEvent.layout.height);
73-
});
68+
setSize(e.nativeEvent.layout);
7469
}, []);
7570

7671
return (

0 commit comments

Comments
 (0)