diff options
author | Santo Cariotti <santo@dcariotti.me> | 2024-08-28 15:53:21 +0200 |
---|---|---|
committer | Santo Cariotti <santo@dcariotti.me> | 2024-08-28 15:53:21 +0200 |
commit | 83643a78b73dee5610be6ad9837fb72e9b944cb7 (patch) | |
tree | 1eca6bad452656f78879c829181362f3b586d697 /components/ParallaxScrollView.tsx |
Initial commit
Generated by create-expo-app 3.0.0.
Diffstat (limited to 'components/ParallaxScrollView.tsx')
-rw-r--r-- | components/ParallaxScrollView.tsx | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/components/ParallaxScrollView.tsx b/components/ParallaxScrollView.tsx new file mode 100644 index 0000000..0a35419 --- /dev/null +++ b/components/ParallaxScrollView.tsx @@ -0,0 +1,76 @@ +import type { PropsWithChildren, ReactElement } from 'react'; +import { StyleSheet, useColorScheme } from 'react-native'; +import Animated, { + interpolate, + useAnimatedRef, + useAnimatedStyle, + useScrollViewOffset, +} from 'react-native-reanimated'; + +import { ThemedView } from '@/components/ThemedView'; + +const HEADER_HEIGHT = 250; + +type Props = PropsWithChildren<{ + headerImage: ReactElement; + headerBackgroundColor: { dark: string; light: string }; +}>; + +export default function ParallaxScrollView({ + children, + headerImage, + headerBackgroundColor, +}: Props) { + const colorScheme = useColorScheme() ?? 'light'; + const scrollRef = useAnimatedRef<Animated.ScrollView>(); + const scrollOffset = useScrollViewOffset(scrollRef); + + const headerAnimatedStyle = useAnimatedStyle(() => { + return { + transform: [ + { + translateY: interpolate( + scrollOffset.value, + [-HEADER_HEIGHT, 0, HEADER_HEIGHT], + [-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75] + ), + }, + { + scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]), + }, + ], + }; + }); + + return ( + <ThemedView style={styles.container}> + <Animated.ScrollView ref={scrollRef} scrollEventThrottle={16}> + <Animated.View + style={[ + styles.header, + { backgroundColor: headerBackgroundColor[colorScheme] }, + headerAnimatedStyle, + ]}> + {headerImage} + </Animated.View> + <ThemedView style={styles.content}>{children}</ThemedView> + </Animated.ScrollView> + </ThemedView> + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + header: { + height: 250, + overflow: 'hidden', + }, + content: { + flex: 1, + padding: 32, + gap: 16, + overflow: 'hidden', + }, +}); |