Skip to content

Commit

Permalink
Merge branch 'main' into feat/smoothing-prop
Browse files Browse the repository at this point in the history
  • Loading branch information
Christoph Pader committed Jan 23, 2023
2 parents 7414a37 + 278c2a8 commit 0d4b228
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 169 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ There are three events fired when the user interacts with the graph:
2. `onPointSelected`: Fired for each point the user pans through. You can use this event to update labels or highlight selection in the graph.
3. `onGestureEnd`: Fired once the user releases his finger and the pan gesture _deactivates_.

Pan gesture can be configures using these props:

1. `panGestureTimeout`: Set timeout for the pan gesture to activate. Set to `0` to start immediately after touch. Defaults to `300`.

Example:

```jsx
Expand Down
4 changes: 3 additions & 1 deletion example/src/data/GraphData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ export function generateRandomGraphData(length: number): GraphPoint[] {
return Array<number>(length)
.fill(0)
.map((_, index) => ({
date: new Date(index),
date: new Date(
new Date(2000, 0, 1).getTime() + 1000 * 60 * 60 * 24 * index
),
value: weightedRandom(10, Math.pow(index + 1, 2)),
}))
}
Expand Down
15 changes: 10 additions & 5 deletions example/src/screens/GraphPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useCallback, useMemo, useState } from 'react'
import { View, StyleSheet, Text, Button } from 'react-native'
import { View, StyleSheet, Text, Button, ScrollView } from 'react-native'
import { LineGraph } from 'react-native-graph'
import StaticSafeAreaInsets from 'react-native-static-safe-area-insets'
import type { GraphRange } from '../../../src/LineGraphProps'
Expand Down Expand Up @@ -104,7 +104,10 @@ export function GraphPage() {

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

<View style={styles.controls}>
<ScrollView
style={styles.controlsScrollView}
contentContainerStyle={styles.controlsScrollViewContent}
>
<Toggle
title="Animated:"
isEnabled={isAnimated}
Expand Down Expand Up @@ -145,7 +148,7 @@ export function GraphPage() {
isEnabled={indicatorPulsating}
setIsEnabled={setIndicatorPulsating}
/>
</View>
</ScrollView>

<View style={styles.spacer} />
</View>
Expand Down Expand Up @@ -181,9 +184,11 @@ const styles = StyleSheet.create({
height: 35,
marginLeft: 5,
},
controls: {
controlsScrollView: {
flexGrow: 1,
justifyContent: 'center',
paddingHorizontal: 15,
},
controlsScrollViewContent: {
justifyContent: 'center',
},
})
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"devDependencies": {
"@react-native-community/eslint-config": "^2.0.0",
"@release-it/conventional-changelog": "^2.0.0",
"@shopify/react-native-skia": "^0.1.136",
"@shopify/react-native-skia": "^0.1.159",
"@types/react": "^17.0.42",
"@types/react-native": "^0.67.4",
"eslint": "^7.2.0",
Expand All @@ -68,13 +68,13 @@
"react": "^17.0.2",
"react-native": "^0.67.4",
"react-native-builder-bob": "^0.18.0",
"react-native-gesture-handler": "^2.5.0",
"react-native-reanimated": "^2.9.1",
"react-native-gesture-handler": "^2.8.0",
"react-native-reanimated": "^2.13.0",
"release-it": "^14.2.2",
"typescript": "^4.4.3"
},
"peerDependencies": {
"@shopify/react-native-skia": "*",
"@shopify/react-native-skia": ">=0.1.157",
"react": "*",
"react-native": "*",
"react-native-gesture-handler": ">=2",
Expand Down Expand Up @@ -126,7 +126,8 @@
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"useTabs": false
"useTabs": false,
"semi": false
},
"react-native-builder-bob": {
"source": "src",
Expand Down
205 changes: 111 additions & 94 deletions src/AnimatedLineGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import Reanimated, {
withDelay,
} from 'react-native-reanimated'
import { getSixDigitHex } from './utils/getSixDigitHex'
import { GestureHandlerRootView, GestureDetector } from 'react-native-gesture-handler'
import { GestureDetector } from 'react-native-gesture-handler'
import { usePanGesture } from './hooks/usePanGesture'
import { getYForX } from './GetYForX'
import { hexToRgba } from './utils/hexToRgba'
Expand All @@ -50,22 +50,19 @@ const INDICATOR_PULSE_BLUR_RADIUS_SMALL =
const INDICATOR_PULSE_BLUR_RADIUS_BIG =
INDICATOR_RADIUS * INDICATOR_BORDER_MULTIPLIER + 20

// weird rea type bug
const ReanimatedView = Reanimated.View as any

export function AnimatedLineGraph({
points,
color,
smoothing = 0.2,
holdDuration = 300,
gradientFillColors,
lineThickness = 3,
range,
enableFadeInMask,
enablePanGesture,
enablePanGesture = false,
onPointSelected,
onGestureStart,
onGestureEnd,
panGestureDelay = 300,
SelectionDot = DefaultSelectionDot,
enableIndicator = false,
indicatorPulsating = false,
Expand All @@ -81,7 +78,10 @@ export function AnimatedLineGraph({
const [height, setHeight] = useState(0)
const interpolateProgress = useValue(0)

const { gesture, isActive, x } = usePanGesture({ holdDuration })
const { gesture, isActive, x } = usePanGesture({
enabled: enablePanGesture,
holdDuration: panGestureDelay,
})
const circleX = useValue(0)
const circleY = useValue(0)
const pathEnd = useValue(0)
Expand Down Expand Up @@ -460,104 +460,124 @@ export function AnimatedLineGraph({
pulseTrigger
)

const axisLabelContainerStyle = {
paddingTop: TopAxisLabel != null ? 20 : 0,
paddingBottom: BottomAxisLabel != null ? 20 : 0,
}

return (
<GestureHandlerRootView>
<View {...props}>
<GestureDetector gesture={enablePanGesture ? gesture : undefined}>
<ReanimatedView style={[styles.container, styles.axisLabelContainer]}>
{/* Top Label (max price) */}
{TopAxisLabel != null && (
<View style={styles.axisRow}>
<TopAxisLabel />
</View>
)}

{/* Actual Skia Graph */}
<View style={styles.container} onLayout={onLayout}>
<Canvas style={styles.svg}>
<Group>
<View {...props}>
<GestureDetector gesture={gesture}>
<Reanimated.View style={[styles.container, axisLabelContainerStyle]}>
{/* Top Label (max price) */}
{TopAxisLabel != null && (
<View style={styles.axisRow}>
<TopAxisLabel />
</View>
)}

{/* Actual Skia Graph */}
<View style={styles.container} onLayout={onLayout}>
{/* Fix for react-native-skia's incorrect type declarations */}
<Canvas
style={styles.svg}
onPointerEnter={undefined}
onPointerEnterCapture={undefined}
onPointerLeave={undefined}
onPointerLeaveCapture={undefined}
onPointerMove={undefined}
onPointerMoveCapture={undefined}
onPointerCancel={undefined}
onPointerCancelCapture={undefined}
onPointerDown={undefined}
onPointerDownCapture={undefined}
onPointerUp={undefined}
onPointerUpCapture={undefined}
accessibilityLabelledBy={undefined}
accessibilityLanguage={undefined}
>
<Group>
<Path
// @ts-ignore
path={path}
strokeWidth={lineThickness}
style="stroke"
strokeJoin="round"
strokeCap="round"
>
<LinearGradient
start={vec(0, 0)}
end={vec(width, 0)}
colors={gradientColors}
positions={positions}
/>
</Path>

{shouldFillGradient && (
<Path
// @ts-ignore
path={path}
strokeWidth={lineThickness}
style="stroke"
strokeJoin="round"
strokeCap="round"
path={gradientPath}
>
<LinearGradient
start={vec(0, 0)}
end={vec(width, 0)}
colors={gradientColors}
positions={positions}
end={vec(0, height)}
colors={gradientFillColors}
/>
</Path>

{shouldFillGradient && (
<Path
// @ts-ignore
path={gradientPath}
>
<LinearGradient
start={vec(0, 0)}
end={vec(0, height)}
colors={gradientFillColors}
/>
</Path>
)}
</Group>

{SelectionDot != null && (
<SelectionDot
isActive={isActive}
color={color}
lineThickness={lineThickness}
circleX={circleX}
circleY={circleY}
/>
)}

{enableIndicator && (
<Group>
{indicatorPulsating && (
<Circle
cx={indicatorX}
cy={indicatorY}
r={indicatorPulseRadius}
opacity={indicatorPulseOpacity}
color={indicatorPulseColor}
style="fill"
/>
)}

<Circle
cx={indicatorX}
cy={indicatorY}
r={indicatorBorderRadius}
color={'#ffffff'}
>
<Shadow dx={2} dy={2} color="rgba(0,0,0,0.2)" blur={4} />
</Circle>
</Group>

{SelectionDot != null && (
<SelectionDot
isActive={isActive}
color={color}
lineThickness={lineThickness}
circleX={circleX}
circleY={circleY}
/>
)}

{enableIndicator && (
<Group>
{indicatorPulsating && (
<Circle
cx={indicatorX}
cy={indicatorY}
r={indicatorRadius}
color={color}
r={indicatorPulseRadius}
opacity={indicatorPulseOpacity}
color={indicatorPulseColor}
style="fill"
/>
</Group>
)}
</Canvas>
</View>
)}

{/* Bottom Label (min price) */}
{BottomAxisLabel != null && (
<View style={styles.axisRow}>
<BottomAxisLabel />
</View>
)}
</ReanimatedView>
</GestureDetector>
</View>
</GestureHandlerRootView>
<Circle
cx={indicatorX}
cy={indicatorY}
r={indicatorBorderRadius}
color={'#ffffff'}
>
<Shadow dx={2} dy={2} color="rgba(0,0,0,0.2)" blur={4} />
</Circle>
<Circle
cx={indicatorX}
cy={indicatorY}
r={indicatorRadius}
color={color}
/>
</Group>
)}
</Canvas>
</View>

{/* Bottom Label (min price) */}
{BottomAxisLabel != null && (
<View style={styles.axisRow}>
<BottomAxisLabel />
</View>
)}
</Reanimated.View>
</GestureDetector>
</View>
)
}

Expand All @@ -568,9 +588,6 @@ const styles = StyleSheet.create({
container: {
flex: 1,
},
axisLabelContainer: {
paddingVertical: 20,
},
axisRow: {
height: 17,
},
Expand Down
Loading

0 comments on commit 0d4b228

Please sign in to comment.