Skip to content

Commit 35ac0f7

Browse files
authored
fix: max min point normalization for multiline
Fixed a bug where union min/max of the series were not being used to draw the lines on the multiline charts. This made it so that all input points were touching the top and bottom of the graph, even though the series' y-values did not match. Now, we introduced a global minY/maxY value to interpolate all lines against.
2 parents 17b6a4d + e212605 commit 35ac0f7

File tree

7 files changed

+56
-24
lines changed

7 files changed

+56
-24
lines changed

example/ios/Podfile.lock

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,17 +131,17 @@ PODS:
131131
- libavif/core
132132
- libevent (2.1.12)
133133
- libvmaf (2.3.1)
134-
- libwebp (1.3.2):
135-
- libwebp/demux (= 1.3.2)
136-
- libwebp/mux (= 1.3.2)
137-
- libwebp/sharpyuv (= 1.3.2)
138-
- libwebp/webp (= 1.3.2)
139-
- libwebp/demux (1.3.2):
134+
- libwebp (1.5.0):
135+
- libwebp/demux (= 1.5.0)
136+
- libwebp/mux (= 1.5.0)
137+
- libwebp/sharpyuv (= 1.5.0)
138+
- libwebp/webp (= 1.5.0)
139+
- libwebp/demux (1.5.0):
140140
- libwebp/webp
141-
- libwebp/mux (1.3.2):
141+
- libwebp/mux (1.5.0):
142142
- libwebp/demux
143-
- libwebp/sharpyuv (1.3.2)
144-
- libwebp/webp (1.3.2):
143+
- libwebp/sharpyuv (1.5.0)
144+
- libwebp/webp (1.5.0):
145145
- libwebp/sharpyuv
146146
- RCT-Folly (2022.05.16.00):
147147
- boost
@@ -1490,7 +1490,7 @@ SPEC CHECKSUMS:
14901490
libavif: 84bbb62fb232c3018d6f1bab79beea87e35de7b7
14911491
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
14921492
libvmaf: 27f523f1e63c694d14d534cd0fddd2fab0ae8711
1493-
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
1493+
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
14941494
RCT-Folly: 7169b2b1c44399c76a47b5deaaba715eeeb476c0
14951495
RCTRequired: ab7f915c15569f04a49669e573e6e319a53f9faa
14961496
RCTTypeSafety: 63b97ced7b766865057e7154db0e81ce4ee6cf1e

src/components/MultiLineChart/InteractiveMultiLineChart.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export const InteractiveMultiLineChart = <Data extends Record<string, [number, n
3232
...viewProps
3333
}: MultiLineChartProps<Data, false>) => {
3434
const [layoutComputed, setLayoutComputed] = useState(false);
35-
const { height, width, setCanvasSize } = useMultiLineChartContext();
35+
const { height, width, minY, maxY, setCanvasSize } = useMultiLineChartContext();
3636

3737
const gestures = useGestures({
3838
points,
@@ -73,6 +73,8 @@ export const InteractiveMultiLineChart = <Data extends Record<string, [number, n
7373
...c.props,
7474
width,
7575
height,
76+
minValue: minY,
77+
maxValue: maxY,
7678
});
7779
});
7880
}
@@ -81,6 +83,8 @@ export const InteractiveMultiLineChart = <Data extends Record<string, [number, n
8183
...invokedChildren.props,
8284
width,
8385
height,
86+
minValue: minY,
87+
maxValue: maxY,
8488
});
8589
})()}
8690

src/components/MultiLineChart/Line.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ interface LineProps extends Pick<PathProps, "children" | "color" | "strokeWidth"
1616
height?: number;
1717
strokeWidth?: number;
1818
curveType?: ComputePathProps["curveType"];
19+
minValue?: number;
20+
maxValue?: number;
1921
}
2022

2123
export const Line: React.FC<LineProps> = ({
@@ -24,14 +26,24 @@ export const Line: React.FC<LineProps> = ({
2426
height = 0,
2527
strokeWidth = 2,
2628
curveType = "linear",
29+
minValue,
30+
maxValue,
2731
...pathProps
2832
}) => {
2933
const data = useMemo(() => {
3034
return computeGraphData(points);
3135
}, [points]);
3236

3337
const path = useMemo(() => {
34-
return computePath({ ...data, width, height, cursorRadius: 0, curveType });
38+
return computePath({
39+
...data,
40+
width,
41+
height,
42+
cursorRadius: 0,
43+
curveType,
44+
minValue: minValue ?? data.minValue,
45+
maxValue: maxValue ?? data.maxValue,
46+
});
3547
}, [data, width, height, curveType]);
3648

3749
return <Path style="stroke" strokeWidth={strokeWidth} color="gray" {...pathProps} path={path} />;

src/components/MultiLineChart/MultiLineChart.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const MultiLineChart = <
2727
...props
2828
}: MultiLineChartProps<Data, Static>) => {
2929
return (
30-
<MultiLineChartProvider>
30+
<MultiLineChartProvider points={props.points}>
3131
{/* <StaticMultiLineChart {...props} /> */}
3232
{isStatic ? (
3333
<StaticMultiLineChart isStatic {...props} />

src/components/MultiLineChart/StaticMultiLineChart.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const StaticMultiLineChart = <Data extends Record<string, [number, number
1313
...viewProps
1414
}: MultiLineChartProps<Data, true>) => {
1515
const [layoutComputed, setLayoutComputed] = useState(false);
16-
const { height, width, setCanvasSize } = useMultiLineChartContext();
16+
const { height, width, minY, maxY, setCanvasSize } = useMultiLineChartContext();
1717

1818
const onLayout = useCallback((e: LayoutChangeEvent) => {
1919
// Batch the updates to avoid unnecessary re-renders
@@ -44,6 +44,8 @@ export const StaticMultiLineChart = <Data extends Record<string, [number, number
4444
...c.props,
4545
width,
4646
height,
47+
minValue: minY,
48+
maxValue: maxY,
4749
});
4850
});
4951
}
@@ -52,6 +54,8 @@ export const StaticMultiLineChart = <Data extends Record<string, [number, number
5254
...invokedChildren.props,
5355
width,
5456
height,
57+
minValue: minY,
58+
maxValue: maxY,
5559
});
5660
})()}
5761
</Canvas>

src/components/MultiLineChart/context.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,43 @@
1-
import { createContext, useContext, useState } from "react";
1+
import { createContext, useContext, useMemo, useState } from "react";
22
import { LayoutRectangle } from "react-native";
33

44
interface MultiLineChartContextState {
55
width: number;
66
height: number;
77
setCanvasSize: React.Dispatch<React.SetStateAction<LayoutRectangle>>;
8+
minY: number;
9+
maxY: number;
810
}
911

1012
export const MultiLineChartContext = createContext<MultiLineChartContextState | undefined>(
1113
undefined
1214
);
1315

1416
interface MultiLineChartProviderProps {
17+
points: Record<string, [number, number][]>;
1518
width?: number;
1619
height?: number;
1720
}
1821

1922
export const MultiLineChartProvider: React.FC<
2023
React.PropsWithChildren<MultiLineChartProviderProps>
21-
> = ({ children }) => {
24+
> = ({ points, children }) => {
2225
const [canvasSize, setCanvasSize] = useState<LayoutRectangle>({
2326
height: 0,
2427
width: 0,
2528
x: 0,
2629
y: 0,
2730
});
2831

32+
const { minY, maxY } = useMemo(() => {
33+
const minY = Math.min(...Object.values(points).map((p) => Math.min(...p.map(([, y]) => y))));
34+
const maxY = Math.max(...Object.values(points).map((p) => Math.max(...p.map(([, y]) => y))));
35+
return { minY, maxY };
36+
}, [points]);
37+
2938
return (
3039
<MultiLineChartContext.Provider
31-
value={{
32-
width: canvasSize.width,
33-
height: canvasSize.height,
34-
setCanvasSize,
35-
}}
40+
value={{ width: canvasSize.width, height: canvasSize.height, setCanvasSize, minY, maxY }}
3641
>
3742
{children}
3843
</MultiLineChartContext.Provider>

src/components/MultiLineChart/useGestures.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export const useGestures = <Data extends Record<string, [number, number][]>>({
105105
onPanGestureChange,
106106
onPanGestureEnd,
107107
}: UseGestureProps<Data>) => {
108-
const { width } = useMultiLineChartContext();
108+
const { width, minY, maxY } = useMultiLineChartContext();
109109

110110
const graphData = useMemo(() => {
111111
return Object.entries(points).reduce(
@@ -122,11 +122,18 @@ export const useGestures = <Data extends Record<string, [number, number][]>>({
122122
const pathKeys = Object.keys(graphData) as (keyof Data)[];
123123
for (const key of pathKeys) {
124124
const value = graphData[key];
125-
results[key] = computePath({ ...value, height, width, curveType });
125+
results[key] = computePath({
126+
...value,
127+
height,
128+
width,
129+
curveType,
130+
minValue: minY, // We use the shared minimum value here since the minimum is shared across all lines
131+
maxValue: maxY, // We use the shared maximum value here since the maximum is shared across all lines
132+
});
126133
}
127134

128135
return results;
129-
}, [graphData, height, width, curveType]);
136+
}, [graphData, height, width, curveType, minY, maxY]);
130137

131138
const paths = useSharedValue<Record<keyof Data, SkPath>>(pathsJS);
132139
useEffect(() => {

0 commit comments

Comments
 (0)