React Native Zoomable View
unknown
typescript
8 months ago
2.0 kB
2
Indexable
import React, {PropsWithChildren} from 'react'; import {Gesture, GestureDetector} from 'react-native-gesture-handler'; import Animated, { clamp, useAnimatedStyle, useSharedValue, withSpring, } from 'react-native-reanimated'; type Props = { minScale?: number; maxScale?: number; }; const ZoomableView = ({ children, maxScale = 1.5, minScale = 1, }: PropsWithChildren<Props>) => { const startScale = useSharedValue(0); const scale = useSharedValue(minScale); const startTranslationX = useSharedValue(0); const translateX = useSharedValue(0); const pinchHandler = Gesture.Pinch() .onBegin(() => { startScale.value = scale.value; }) .onUpdate(({scale: eScale}) => { scale.value = clamp(startScale.value * eScale, minScale, maxScale); }) .onEnd(() => { if (scale.value <= minScale) { scale.value = withSpring(minScale); translateX.value = withSpring(0); } }); const panHandler = Gesture.Pan() .onBegin(() => { if (scale.value <= minScale) return; startTranslationX.value = translateX.value; }) .onUpdate(({translationX}) => { if (scale.value > minScale) { translateX.value = clamp( startTranslationX.value + translationX, -100, 100, ); } }); const tapHandler = Gesture.Tap() .numberOfTaps(2) .onEnd(() => { scale.value = withSpring(scale.value > minScale ? minScale : maxScale); translateX.value = withSpring(0); }); const animatedStyle = useAnimatedStyle(() => { return { transform: [{scale: scale.value}, {translateX: translateX.value}], }; }); const gesture = Gesture.Simultaneous(pinchHandler, panHandler, tapHandler); return ( <GestureDetector gesture={gesture}> <Animated.View style={[{flex: 1}, animatedStyle]}> {children} </Animated.View> </GestureDetector> ); }; export default ZoomableView;
Editor is loading...
Leave a Comment