React Native useAnimatedGestureHandler在Web上仅在onStart中没有被调用
P粉667649253
P粉667649253 2023-08-16 15:21:08
[React讨论组]
<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> <pre class="brush:php;toolbar:false;">import { View, Image } from 'react-native'; import Animated, { useAnimatedStyle, useSharedValue, useAnimatedGestureHandler, withSpring, } from 'react-native-reanimated'; import { PanGestureHandler, TapGestureHandler } 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 onDoubleTap = useAnimatedGestureHandler({ onActive: () =&gt; { if (scaleImage.value !== imageSize * 2) { scaleImage.value = scaleImage.value * 2; } else { scaleImage.value = scaleImage.value / 2; } }, }); const onDrag = useAnimatedGestureHandler({ onStart: (event, context) =&gt; { context.translateX = translateX.value; context.translateY = translateY.value; }, onActive: (event, context) =&gt; { translateX.value = event.translationX + context.translateX; translateY.value = event.translationY + context.translateY; }, }); const imageStyle = useAnimatedStyle(() =&gt; { return { width: withSpring(scaleImage.value), height: withSpring(scaleImage.value), }; }); const containerStyle = useAnimatedStyle(() =&gt; { return { transform: [ { translateX: translateX.value, }, { translateY: translateY.value, }, ], }; }); return ( &lt;PanGestureHandler onGestureEvent={onDrag}&gt; &lt;AnimatedView style={[containerStyle, { top: -350 }]}&gt; &lt;TapGestureHandler onGestureEvent={onDoubleTap} numberOfTaps={2}&gt; &lt;AnimatedImage source={stickerSource} resizeMode='contain' style={[imageStyle, { width: imageSize, height: imageSize }]} /&gt; &lt;/TapGestureHandler&gt; &lt;/AnimatedView&gt; &lt;/PanGestureHandler&gt; ); }</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粉667649253
P粉667649253

全部回复(1)
P粉293550575

我通过查阅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>
  );
}
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号