首页  >  问答  >  正文

React Native useAnimatedGestureHandler在Web上仅在onStart中没有被调用

<p><strong>在我意识到 onStart() 没有被调用之前</strong></p> <p>在 Web 上使用 PanGestureHandler 并尝试“拖动” AnimatedView 在 Web 上不起作用。没有明显的错误,应用程序构建正常,检查时控制台没有警告。</p> <p>有一个警告让我相信这可能是问题的根源。我在控制台上收到一个警告,内容如下:</p> <p><code>"transform" 样式数组值已弃用。请使用以空格分隔的字符串函数,例如 "scaleX(2) rotateX(15deg)"。</code></p> <p>我使用的是带有 containerStyle 的 AnimatedView 来对对象进行变换和拖动时的移动。</p> <p><strong>问题的根源</strong></p> <p>所以我进一步研究了这个问题,试图调试它,我意识到 onStart() 回调没有被调用。由于 onStart() 回调没有被调用,上下文值永远不会被设置,上下文对象整体上保持为空。这导致了我最初的问题,无法拖动对象。</p> <p>不过,在 iOS 上仍然可以工作。出于某种原因,在 iOS 上 onStart() 回调被调用。这导致上下文被填充并且工作正常。</p> <p>这是我的代码,记住这只是一个组件。在根目录中,我确实有一个 GestureHandlerRootView 组件包装整个应用程序。</p>
从 'react-native' 导入 { View, Image };
导入动画,{
    使用动画样式,
    使用共享值,
    使用AnimatedGestureHandler,
    随着春天,
来自“react-native-reanimated”;
从 'react-native-gesture-handler' 导入 { PanGestureHandler, TapGestureHandler };

const AnimatedImage = Animated.createAnimatedComponent(Image);
const AnimatedView = Animated.createAnimatedComponent(View);

导出默认函数 EmojiSticker ({ imageSize, StickerSource }) {
    const scaleImage = useSharedValue(imageSize);
    const translateX = useSharedValue(0);
    consttranslateY = useSharedValue(0);

    const onDoubleTap = useAnimatedGestureHandler({
        onActive: () =>; {
            if (scaleImage.value !== imageSize * 2) {
                缩放图像.值 = 缩放图像.值 * 2;
            } 别的 {
                缩放图像.值 = 缩放图像.值 / 2;
            }
        },
    });
    const onDrag = useAnimatedGestureHandler({
        onStart: (事件, 上下文) => {
            context.translateX = translateX.value;
            context.translateY = translateY.value;
        },
        onActive: (事件, 上下文) => {
            translateX.value = event.translationX + context.translateX;
            translateY.value = event.translationY + context.translateY;
        },
    });
    
    const imageStyle = useAnimatedStyle(() => {
        返回 {
            宽度:withSpring(scaleImage.value),
            高度:withSpring(scaleImage.value),
        };
    });
    const containerStyle = useAnimatedStyle(() => {
        返回 {
            转换: [
                {
                    翻译X:翻译X.值,
                },
                {
                    翻译Y:翻译Y.值,
                },
            ],
        };
    });

    返回 (
        
            <AnimatedView style={[containerStyle, { top: -350 }]}>
                
                    <动画图像 
                        来源={贴纸源}
                        resizeMode='包含'
                        样式={[imageStyle, { 宽度: imageSize, 高度: imageSize }]}
                    >>
                </TapGestureHandler>
            </动画视图>
        </PanGestureHandler>
    );
}</pre>
<p><strong>顺便说一下,晚餐在 Web 和 iOS 上都完美工作。</strong> 我感到很困惑,因为拖动在 iOS 上完美工作,但在 Web 上却行得通。transform 样式的弃用使我尝试找出一种创建特定于 Web 的样式的方法,但我很难找到其他人遇到这个问题的情况。我相信有一个真正的解决方案,只是我可能遗漏了。我只是真的很困惑,因为它在 iOS 上完美工作,但在 Web 上却不行。</p>
<p>我尝试查看是否有其他人遇到类似的问题,但实际上没有找到任何相关的内容。我还尝试在控制台上搜索我看到的警告。</p>
<p><code>"transform" 样式数组值已弃用。请使用以空格分隔的字符串函数,例如 "scaleX(2) rotateX(15deg)"。</code></p>
<p>至少在我搜索与 React-Native 相关的内容时,我没有找到任何相关的内容。</p>
<p>我希望能找到一个在 Web 上可拖动的解决方案。</p>
P粉667649253P粉667649253401 天前443

全部回复(1)我来回复

  • P粉293550575

    P粉2935505752023-08-17 11:02:56

    我通过查阅react-native-reanimated的文档来解决了这个问题。显然,useAnimatedGestureHandler并没有被弃用,因为它在onDoubleTap中起作用,更不用说onDrag在iOS上也正常工作。

    但是在处理平移手势的文档中,我找到了这个:

    const pan = Gesture.Pan()
      .onBegin(() => {
        pressed.value = true;
      })
      .onChange((event) => {
        offset.value = event.translationX;
      })
      .onFinalize(() => {
        offset.value = withSpring(0);
        pressed.value = false;
      });

    所以,不需要从'react-native-gesture-handler'中导入PanGestureHandlerTapGestureHandler,也不需要从'react-native-reanimated'中导入useAnimatedGestureHandler,只需要从'react-native-gesture-handler'中导入GestureGestureDetector

    Gesture取代了useAnimatedGestureHandler,而GestureDetector取代了PanGestureHandlerTapGestureHandler等组件。

    我还需要使用useSharedValue()创建自己的contextXcontextY变量,因为据我所知,onBegin()onChange()回调函数没有可设置的上下文。

    无论如何,这是修复后的代码,现在在Web和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>
      );
    }

    回复
    0
  • 取消回复