React Native useAnimatedGestureHandler在Web上僅在onStart中沒有被調用
P粉667649253
P粉667649253 2023-08-16 15:21:08
0
1
531
<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粉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>
  );
}
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板