P粉2935505752023-08-17 11:02:56
I solved this problem by consulting the documentation of react-native-reanimated
. Apparently useAnimatedGestureHandler
is not deprecated as it works in onDoubleTap
, not to mention onDrag
also works fine on iOS.
But in the documentation dealing with pan gestures I found this:
const pan = Gesture.Pan() .onBegin(() => { pressed.value = true; }) .onChange((event) => { offset.value = event.translationX; }) .onFinalize(() => { offset.value = withSpring(0); pressed.value = false; });
So, there is no need to import PanGestureHandler
and TapGestureHandler
from 'react-native-gesture-handler', nor from 'react-native-reanimated' useAnimatedGestureHandler
, just import Gesture
and GestureDetector
from 'react-native-gesture-handler'.
Gesture
replaces useAnimatedGestureHandler
, and GestureDetector
replaces components such as PanGestureHandler
and TapGestureHandler
.
I also need to create my own contextX
and contextY
variables using useSharedValue()
because as far as I know, onBegin()
andonChange()
The callback function has no context to set.
Anyway, here is the fixed code, which now runs perfectly on both the web and iOS:
import { View, Image } from 'react-native'; import Animated, { useAnimatedStyle, useSharedValue, withSpring, } from 'react-native-reanimated'; import { Gesture, GestureDetector } from 'react-native-gesture-handler'; const AnimatedImage = Animated.createAnimatedComponent(Image); const AnimatedView = Animated.createAnimatedComponent(View); export default function EmojiSticker({ imageSize, stickerSource }) { const scaleImage = useSharedValue(imageSize); const translateX = useSharedValue(0); const translateY = useSharedValue(0); const contextX = useSharedValue(0); const contextY = useSharedValue(0); const onDoubleTap = Gesture.Tap().numberOfTaps(2) .onEnd(() => { if (scaleImage.value !== imageSize * 2) { scaleImage.value = scaleImage.value * 2; } else { scaleImage.value = scaleImage.value / 2; } }); const onDrag = Gesture.Pan() .onBegin(() => { contextX.value = translateX.value; contextY.value = translateY.value; }) .onChange((event) => { translateX.value = event.translationX + contextX.value; translateY.value = event.translationY + contextY.value; }); const imageStyle = useAnimatedStyle(() => { return { width: withSpring(scaleImage.value), height: withSpring(scaleImage.value), }; }); const containerStyle = useAnimatedStyle(() => { return { transform: [ { translateX: translateX.value, }, { translateY: translateY.value, }, ], }; }); return ( <GestureDetector gesture={onDrag}> <AnimatedView style={[containerStyle, { top: -350 }]}> <GestureDetector gesture={onDoubleTap}> <AnimatedImage source={stickerSource} resizeMode="contain" style={[imageStyle, { width: imageSize, height: imageSize }]} /> </GestureDetector> </AnimatedView> </GestureDetector> ); }