Skip to content

Commit 0d4b228

Browse files
author
Christoph Pader
committed
Merge branch 'main' into feat/smoothing-prop
2 parents 7414a37 + 278c2a8 commit 0d4b228

10 files changed

Lines changed: 203 additions & 169 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ There are three events fired when the user interacts with the graph:
8282
2. `onPointSelected`: Fired for each point the user pans through. You can use this event to update labels or highlight selection in the graph.
8383
3. `onGestureEnd`: Fired once the user releases his finger and the pan gesture _deactivates_.
8484

85+
Pan gesture can be configures using these props:
86+
87+
1. `panGestureTimeout`: Set timeout for the pan gesture to activate. Set to `0` to start immediately after touch. Defaults to `300`.
88+
8589
Example:
8690

8791
```jsx

example/src/data/GraphData.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ export function generateRandomGraphData(length: number): GraphPoint[] {
1111
return Array<number>(length)
1212
.fill(0)
1313
.map((_, index) => ({
14-
date: new Date(index),
14+
date: new Date(
15+
new Date(2000, 0, 1).getTime() + 1000 * 60 * 60 * 24 * index
16+
),
1517
value: weightedRandom(10, Math.pow(index + 1, 2)),
1618
}))
1719
}

example/src/screens/GraphPage.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { useCallback, useMemo, useState } from 'react'
2-
import { View, StyleSheet, Text, Button } from 'react-native'
2+
import { View, StyleSheet, Text, Button, ScrollView } from 'react-native'
33
import { LineGraph } from 'react-native-graph'
44
import StaticSafeAreaInsets from 'react-native-static-safe-area-insets'
55
import type { GraphRange } from '../../../src/LineGraphProps'
@@ -104,7 +104,10 @@ export function GraphPage() {
104104

105105
<Button title="Refresh" onPress={refreshData} />
106106

107-
<View style={styles.controls}>
107+
<ScrollView
108+
style={styles.controlsScrollView}
109+
contentContainerStyle={styles.controlsScrollViewContent}
110+
>
108111
<Toggle
109112
title="Animated:"
110113
isEnabled={isAnimated}
@@ -145,7 +148,7 @@ export function GraphPage() {
145148
isEnabled={indicatorPulsating}
146149
setIsEnabled={setIndicatorPulsating}
147150
/>
148-
</View>
151+
</ScrollView>
149152

150153
<View style={styles.spacer} />
151154
</View>
@@ -181,9 +184,11 @@ const styles = StyleSheet.create({
181184
height: 35,
182185
marginLeft: 5,
183186
},
184-
controls: {
187+
controlsScrollView: {
185188
flexGrow: 1,
186-
justifyContent: 'center',
187189
paddingHorizontal: 15,
188190
},
191+
controlsScrollViewContent: {
192+
justifyContent: 'center',
193+
},
189194
})

package.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
"devDependencies": {
5858
"@react-native-community/eslint-config": "^2.0.0",
5959
"@release-it/conventional-changelog": "^2.0.0",
60-
"@shopify/react-native-skia": "^0.1.136",
60+
"@shopify/react-native-skia": "^0.1.159",
6161
"@types/react": "^17.0.42",
6262
"@types/react-native": "^0.67.4",
6363
"eslint": "^7.2.0",
@@ -68,13 +68,13 @@
6868
"react": "^17.0.2",
6969
"react-native": "^0.67.4",
7070
"react-native-builder-bob": "^0.18.0",
71-
"react-native-gesture-handler": "^2.5.0",
72-
"react-native-reanimated": "^2.9.1",
71+
"react-native-gesture-handler": "^2.8.0",
72+
"react-native-reanimated": "^2.13.0",
7373
"release-it": "^14.2.2",
7474
"typescript": "^4.4.3"
7575
},
7676
"peerDependencies": {
77-
"@shopify/react-native-skia": "*",
77+
"@shopify/react-native-skia": ">=0.1.157",
7878
"react": "*",
7979
"react-native": "*",
8080
"react-native-gesture-handler": ">=2",
@@ -126,7 +126,8 @@
126126
"singleQuote": true,
127127
"tabWidth": 2,
128128
"trailingComma": "es5",
129-
"useTabs": false
129+
"useTabs": false,
130+
"semi": false
130131
},
131132
"react-native-builder-bob": {
132133
"source": "src",

src/AnimatedLineGraph.tsx

Lines changed: 111 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ import Reanimated, {
3838
withDelay,
3939
} from 'react-native-reanimated'
4040
import { getSixDigitHex } from './utils/getSixDigitHex'
41-
import { GestureHandlerRootView, GestureDetector } from 'react-native-gesture-handler'
41+
import { GestureDetector } from 'react-native-gesture-handler'
4242
import { usePanGesture } from './hooks/usePanGesture'
4343
import { getYForX } from './GetYForX'
4444
import { hexToRgba } from './utils/hexToRgba'
@@ -50,22 +50,19 @@ const INDICATOR_PULSE_BLUR_RADIUS_SMALL =
5050
const INDICATOR_PULSE_BLUR_RADIUS_BIG =
5151
INDICATOR_RADIUS * INDICATOR_BORDER_MULTIPLIER + 20
5252

53-
// weird rea type bug
54-
const ReanimatedView = Reanimated.View as any
55-
5653
export function AnimatedLineGraph({
5754
points,
5855
color,
5956
smoothing = 0.2,
60-
holdDuration = 300,
6157
gradientFillColors,
6258
lineThickness = 3,
6359
range,
6460
enableFadeInMask,
65-
enablePanGesture,
61+
enablePanGesture = false,
6662
onPointSelected,
6763
onGestureStart,
6864
onGestureEnd,
65+
panGestureDelay = 300,
6966
SelectionDot = DefaultSelectionDot,
7067
enableIndicator = false,
7168
indicatorPulsating = false,
@@ -81,7 +78,10 @@ export function AnimatedLineGraph({
8178
const [height, setHeight] = useState(0)
8279
const interpolateProgress = useValue(0)
8380

84-
const { gesture, isActive, x } = usePanGesture({ holdDuration })
81+
const { gesture, isActive, x } = usePanGesture({
82+
enabled: enablePanGesture,
83+
holdDuration: panGestureDelay,
84+
})
8585
const circleX = useValue(0)
8686
const circleY = useValue(0)
8787
const pathEnd = useValue(0)
@@ -460,104 +460,124 @@ export function AnimatedLineGraph({
460460
pulseTrigger
461461
)
462462

463+
const axisLabelContainerStyle = {
464+
paddingTop: TopAxisLabel != null ? 20 : 0,
465+
paddingBottom: BottomAxisLabel != null ? 20 : 0,
466+
}
467+
463468
return (
464-
<GestureHandlerRootView>
465-
<View {...props}>
466-
<GestureDetector gesture={enablePanGesture ? gesture : undefined}>
467-
<ReanimatedView style={[styles.container, styles.axisLabelContainer]}>
468-
{/* Top Label (max price) */}
469-
{TopAxisLabel != null && (
470-
<View style={styles.axisRow}>
471-
<TopAxisLabel />
472-
</View>
473-
)}
474-
475-
{/* Actual Skia Graph */}
476-
<View style={styles.container} onLayout={onLayout}>
477-
<Canvas style={styles.svg}>
478-
<Group>
469+
<View {...props}>
470+
<GestureDetector gesture={gesture}>
471+
<Reanimated.View style={[styles.container, axisLabelContainerStyle]}>
472+
{/* Top Label (max price) */}
473+
{TopAxisLabel != null && (
474+
<View style={styles.axisRow}>
475+
<TopAxisLabel />
476+
</View>
477+
)}
478+
479+
{/* Actual Skia Graph */}
480+
<View style={styles.container} onLayout={onLayout}>
481+
{/* Fix for react-native-skia's incorrect type declarations */}
482+
<Canvas
483+
style={styles.svg}
484+
onPointerEnter={undefined}
485+
onPointerEnterCapture={undefined}
486+
onPointerLeave={undefined}
487+
onPointerLeaveCapture={undefined}
488+
onPointerMove={undefined}
489+
onPointerMoveCapture={undefined}
490+
onPointerCancel={undefined}
491+
onPointerCancelCapture={undefined}
492+
onPointerDown={undefined}
493+
onPointerDownCapture={undefined}
494+
onPointerUp={undefined}
495+
onPointerUpCapture={undefined}
496+
accessibilityLabelledBy={undefined}
497+
accessibilityLanguage={undefined}
498+
>
499+
<Group>
500+
<Path
501+
// @ts-ignore
502+
path={path}
503+
strokeWidth={lineThickness}
504+
style="stroke"
505+
strokeJoin="round"
506+
strokeCap="round"
507+
>
508+
<LinearGradient
509+
start={vec(0, 0)}
510+
end={vec(width, 0)}
511+
colors={gradientColors}
512+
positions={positions}
513+
/>
514+
</Path>
515+
516+
{shouldFillGradient && (
479517
<Path
480518
// @ts-ignore
481-
path={path}
482-
strokeWidth={lineThickness}
483-
style="stroke"
484-
strokeJoin="round"
485-
strokeCap="round"
519+
path={gradientPath}
486520
>
487521
<LinearGradient
488522
start={vec(0, 0)}
489-
end={vec(width, 0)}
490-
colors={gradientColors}
491-
positions={positions}
523+
end={vec(0, height)}
524+
colors={gradientFillColors}
492525
/>
493526
</Path>
494-
495-
{shouldFillGradient && (
496-
<Path
497-
// @ts-ignore
498-
path={gradientPath}
499-
>
500-
<LinearGradient
501-
start={vec(0, 0)}
502-
end={vec(0, height)}
503-
colors={gradientFillColors}
504-
/>
505-
</Path>
506-
)}
507-
</Group>
508-
509-
{SelectionDot != null && (
510-
<SelectionDot
511-
isActive={isActive}
512-
color={color}
513-
lineThickness={lineThickness}
514-
circleX={circleX}
515-
circleY={circleY}
516-
/>
517527
)}
518-
519-
{enableIndicator && (
520-
<Group>
521-
{indicatorPulsating && (
522-
<Circle
523-
cx={indicatorX}
524-
cy={indicatorY}
525-
r={indicatorPulseRadius}
526-
opacity={indicatorPulseOpacity}
527-
color={indicatorPulseColor}
528-
style="fill"
529-
/>
530-
)}
531-
532-
<Circle
533-
cx={indicatorX}
534-
cy={indicatorY}
535-
r={indicatorBorderRadius}
536-
color={'#ffffff'}
537-
>
538-
<Shadow dx={2} dy={2} color="rgba(0,0,0,0.2)" blur={4} />
539-
</Circle>
528+
</Group>
529+
530+
{SelectionDot != null && (
531+
<SelectionDot
532+
isActive={isActive}
533+
color={color}
534+
lineThickness={lineThickness}
535+
circleX={circleX}
536+
circleY={circleY}
537+
/>
538+
)}
539+
540+
{enableIndicator && (
541+
<Group>
542+
{indicatorPulsating && (
540543
<Circle
541544
cx={indicatorX}
542545
cy={indicatorY}
543-
r={indicatorRadius}
544-
color={color}
546+
r={indicatorPulseRadius}
547+
opacity={indicatorPulseOpacity}
548+
color={indicatorPulseColor}
549+
style="fill"
545550
/>
546-
</Group>
547-
)}
548-
</Canvas>
549-
</View>
551+
)}
550552

551-
{/* Bottom Label (min price) */}
552-
{BottomAxisLabel != null && (
553-
<View style={styles.axisRow}>
554-
<BottomAxisLabel />
555-
</View>
556-
)}
557-
</ReanimatedView>
558-
</GestureDetector>
559-
</View>
560-
</GestureHandlerRootView>
553+
<Circle
554+
cx={indicatorX}
555+
cy={indicatorY}
556+
r={indicatorBorderRadius}
557+
color={'#ffffff'}
558+
>
559+
<Shadow dx={2} dy={2} color="rgba(0,0,0,0.2)" blur={4} />
560+
</Circle>
561+
<Circle
562+
cx={indicatorX}
563+
cy={indicatorY}
564+
r={indicatorRadius}
565+
color={color}
566+
/>
567+
</Group>
568+
)}
569+
</Canvas>
570+
</View>
571+
572+
{/* Bottom Label (min price) */}
573+
{BottomAxisLabel != null && (
574+
<View style={styles.axisRow}>
575+
<BottomAxisLabel />
576+
</View>
577+
)}
578+
</Reanimated.View>
579+
</GestureDetector>
580+
</View>
561581
)
562582
}
563583

@@ -568,9 +588,6 @@ const styles = StyleSheet.create({
568588
container: {
569589
flex: 1,
570590
},
571-
axisLabelContainer: {
572-
paddingVertical: 20,
573-
},
574591
axisRow: {
575592
height: 17,
576593
},

0 commit comments

Comments
 (0)