React Native useAnimatedGestureHandler wird nicht nur in onStart im Web aufgerufen
P粉667649253
P粉667649253 2023-08-16 15:21:08
0
1
547
<p><strong>Bevor mir klar wurde, dass onStart() nicht aufgerufen wurde</strong></p> <p>Die Verwendung von PanGestureHandler im Web und der Versuch, eine AnimatedView zu „ziehen“, funktioniert im Web nicht. Es liegen keine offensichtlichen Fehler vor, die Anwendung wird einwandfrei erstellt und bei der Überprüfung werden in der Konsole keine Warnungen angezeigt. </p> <p>Es gibt eine Warnung, die mich vermuten lässt, dass dies die Ursache des Problems sein könnte. Ich erhalte eine Warnung auf der Konsole, die lautet: </p> <p><code>Array-Werte im „Transform“-Stil sind veraltet. Bitte verwenden Sie eine durch Leerzeichen getrennte Zeichenfolgenfunktion, z. B. „scaleX(2) rotationX(15deg)“. </code></p> <p>Ich verwende eine AnimatedView mit containerStyle, um Objekte beim Ziehen zu transformieren und zu verschieben. </p> <p><strong>Die Wurzel des Problems</strong></p> <p>Also habe ich das Problem weiter untersucht und versucht, es zu debuggen, und mir ist aufgefallen, dass der onStart()-Rückruf nicht aufgerufen wurde. Da der onStart()-Callback nicht aufgerufen wird, wird der Kontextwert nie gesetzt und das Kontextobjekt bleibt insgesamt leer. Dies führte zu meinem ursprünglichen Problem, nämlich dass ich keine Objekte ziehen konnte. </p> <p>Es funktioniert jedoch weiterhin unter iOS. Aus irgendeinem Grund wird unter iOS der Rückruf onStart() aufgerufen. Dies führt dazu, dass der Kontext gefüllt ist und einwandfrei funktioniert. </p> <p>Das ist mein Code. Denken Sie daran, dass dies nur eine Komponente ist. Im Stammverzeichnis habe ich eine GestureHandlerRootView-Komponente, die die gesamte Anwendung umschließt.</p> <pre class="brush:php;toolbar:false;">import { View, Image } from 'react-native'; animiert importieren, { useAnimatedStyle, useSharedValue, useAnimatedGestureHandler, mitFrühling, } von 'react-native-reanimated'; import { PanGestureHandler, TapGestureHandler } from 'react-native-gesture-handler'; const AnimatedImage = Animated.createAnimatedComponent(Image); const AnimatedView = Animated.createAnimatedComponent(View); Exportieren Sie die Standardfunktion EmojiSticker ({ imageSize, stickerSource }) { const scaleImage = useSharedValue(imageSize); const translatorX = useSharedValue(0); const TranslateY = useSharedValue(0); const onDoubleTap = useAnimatedGestureHandler({ onActive: () => { if (scaleImage.value !== imageSize * 2) { ScaleImage.value = ScaleImage.value * 2; } anders { ScaleImage.value = ScaleImage.value / 2; } }, }); const onDrag = useAnimatedGestureHandler({ onStart: (Ereignis, Kontext) => { context.translateX = translatorX.value; context.translateY = translatorY.value; }, onActive: (Ereignis, Kontext) => { translatorX.value = event.translationX + context.translateX; translatorY.value = event.translationY + context.translateY; }, }); const imageStyle = useAnimatedStyle(() => { zurückkehren { Breite: withSpring(scaleImage.value), Höhe: withSpring(scaleImage.value), }; }); const containerStyle = useAnimatedStyle(() => { zurückkehren { transformieren: [ { TranslateX: TranslateX.value, }, { TranslateY: TranslateY.value, }, ], }; }); zurückkehren ( <PanGestureHandler onGestureEvent={onDrag}> <AnimatedView style={[containerStyle, { top: -350 }]}> <TapGestureHandler onGestureEvent={onDoubleTap} numberOfTaps={2}> <AnimatedImage source={stickerSource} resizeMode='contain' style={[imageStyle, { width: imageSize, height: imageSize }]} /> </TapGestureHandler> </AnimatedView> </PanGestureHandler> ); }</pre> <p><strong>顺便说一下,双击手势在 Web 和 iOS 上都完美工作.</strong> 我感到困惑, 因为拖动在 iOS 上完美工作, 但在 Web 上却不行.Aufgrund der Abschaffung des Transformationsstils versuche ich, eine Möglichkeit zu finden, webspezifische Stile zu erstellen, aber es fällt mir schwer, eine Situation zu finden, in der andere auf dieses Problem gestoßen sind. Ich glaube, dass es eine echte Lösung gibt, aber vielleicht übersehe ich sie. Ich bin nur wirklich verwirrt, weil es unter iOS perfekt funktioniert, aber nicht im Web. </p> <p>Ich habe versucht herauszufinden, ob noch jemand ein ähnliches Problem hatte, habe aber nichts Relevantes gefunden. Ich habe auch versucht, auf der Konsole nach der Warnung zu suchen, die ich gesehen habe. </p> <p><code>Array-Werte im „Transform“-Stil sind veraltet. Bitte verwenden Sie eine durch Leerzeichen getrennte Zeichenfolgenfunktion, z. B. „scaleX(2) rotationX(15deg)“. </code></p> <p>Zumindest als ich nach etwas gesucht habe, das mit React-Native zu tun hat, habe ich nichts Ähnliches gefunden. </p> <p>Ich würde gerne eine ziehbare Lösung im Internet finden. </p>
P粉667649253
P粉667649253

Antworte allen(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>
  );
}
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage