搜尋

首頁  >  問答  >  主體

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.值,
                },
            ],
        };
    });

    返回 (
        
            >
                
                    <動畫影像
                        來源={貼紙來源}
                        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粉667649253552 天前673

全部回覆(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
  • 取消回覆