React Native useAnimatedGestureHandler n'est pas appelé uniquement dans onStart sur le Web
P粉667649253
P粉667649253 2023-08-16 15:21:08
0
1
514
<p><strong>Avant de réaliser que onStart() n'était pas appelé</strong></p> <p>Utiliser PanGestureHandler sur le Web et essayer de « faire glisser » une AnimatedView ne fonctionne pas sur le Web. Il n'y a pas d'erreurs évidentes, l'application se construit correctement et il n'y a aucun avertissement dans la console lors de la vérification. </p> <p>Un avertissement m'amène à croire que cela pourrait être la source du problème. Je reçois un avertissement sur la console indiquant : </p> <p><code> Les valeurs des tableaux de style « transform » sont obsolètes. Veuillez utiliser une fonction de chaîne délimitée par des espaces, telle que "scaleX(2) rotateX(15deg)". </code></p> <p>J'utilise AnimatedView avec containersStyle pour transformer et déplacer des objets lorsqu'ils sont déplacés. </p> <p><strong>La racine du problème</strong></p> <p>J'ai donc approfondi le problème, en essayant de le déboguer, et j'ai réalisé que le rappel onStart() n'était pas appelé. Puisque le rappel onStart() n’est pas appelé, la valeur du contexte n’est jamais définie et l’objet contexte reste globalement vide. Cela a conduit à mon problème initial, à savoir l'incapacité de faire glisser des objets. </p> <p>Cependant, cela fonctionnera toujours sur iOS. Pour une raison quelconque, sur iOS, le rappel onStart() est appelé. Cela permet au contexte d'être rempli et de fonctionner correctement. </p> <p> Ceci est mon code, rappelez-vous qu'il ne s'agit que d'un composant. Dans le répertoire racine, j'ai un composant GestureHandlerRootView encapsulant l'intégralité de l'application.</p> <pre class="brush:php;toolbar:false;">import {View, Image} depuis 'react-native' ; importer animé, { utiliserAnimatedStyle, utiliserSharedValue, utilisezAnimatedGestureHandler, avecPrintemps, } de 'react-native-reanimated'; importer { PanGestureHandler, TapGestureHandler } depuis 'react-native-gesture-handler' ; const AnimatedImage = Animated.createAnimatedComponent(Image); const AnimatedView = Animated.createAnimatedComponent(View); exporter la fonction par défaut EmojiSticker ({ imageSize, stickerSource }) { const scaleImage = useSharedValue(imageSize); const traduireX = useSharedValue(0); const traduireY = useSharedValue(0); const onDoubleTap = useAnimatedGestureHandler({ onActive : () => { if (scaleImage.value !== imageSize * 2) { scaleImage.value = scaleImage.value * 2; } autre { scaleImage.value = scaleImage.value / 2; } }, }); const onDrag = useAnimatedGestureHandler({ onStart : (événement, contexte) => { contexte.translateX = traduireX.value; contexte.translateY = traduireY.value; }, onActive : (événement, contexte) => { traduireX.value = event.translationX + contexte.translateX; traduireY.value = event.translationY + contexte.translateY; }, }); const imageStyle = useAnimatedStyle(() => { retour { largeur : avecSpring(scaleImage.value), hauteur : avecSpring(scaleImage.value), } ; }); const conteneurStyle = useAnimatedStyle(() => { retour { transformer: [ { traduireX : traduireX.value, }, { traduireY : traduireY.value, }, ], } ; }); retour ( <PanGestureHandler onGestureEvent={onDrag}> <AnimatedView style={[containerStyle, { top : -350 }]}> <TapGestureHandler onGestureEvent={onDoubleTap} numberOfTaps={2}> <Image animée source={stickerSource} resizeMode='contenir' style={[imageStyle, { largeur : tailleimage, hauteur : tailleimage }]} /> </TapGestureHandler> </VueAnimée> </PanGestureHandler> ); }</pré> <p><strong>顺便说一下,双击手势在 Web et iOS 上都完美工作。</strong> Il s'agit d'une version iOS, d'une version Web et d'une version Web.La dépréciation du style de transformation m'a amené à essayer de trouver un moyen de créer des styles spécifiques au Web, mais j'ai du mal à trouver une situation dans laquelle d'autres ont rencontré ce problème. Je crois qu'il existe une vraie solution, mais je la manque peut-être. Je suis vraiment confus car cela fonctionne parfaitement sur iOS mais pas sur le Web. </p> <p>J'ai essayé de voir si quelqu'un d'autre avait un problème similaire, mais je n'ai rien trouvé de pertinent. J'ai également essayé de rechercher sur la console l'avertissement que j'ai vu. </p> <p><code> Les valeurs des tableaux de style "transform" sont obsolètes. Veuillez utiliser une fonction de chaîne délimitée par des espaces, telle que "scaleX(2) rotateX(15deg)". </code></p> <p>Au moins lorsque j'ai recherché quelque chose en rapport avec React-Native, je n'ai rien trouvé en rapport. </p> <p>J'aimerais trouver une solution déplaçable sur le Web. </p>
P粉667649253
P粉667649253

répondre à tous(1)
P粉293550575

Je l'ai vérifiéreact-native-reanimated的文档来解决了这个问题。显然,useAnimatedGestureHandler并没有被弃用,因为它在onDoubleTap中起作用,更不用说onDrag et cela fonctionne également bien sur iOS.

Mais dans la documentation traitant des gestes panoramiques j'ai trouvé ceci :

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

Donc, pas besoin d'importer PanGestureHandlerTapGestureHandler,也不需要从'react-native-reanimated'中导入useAnimatedGestureHandler,只需要从'react-native-gesture-handler'中导入GestureGestureDetector depuis 'react-native-gesture-handler'.

Gesture取代了useAnimatedGestureHandler,而GestureDetector取代了PanGestureHandlerTapGestureHandler et autres composants.

Je dois également utiliser useSharedValue()创建自己的contextXcontextY变量,因为据我所知,onBegin()onChange()La fonction de rappel n'a pas de contexte réglable.

Quoi qu'il en soit, voici le code corrigé, qui fonctionne désormais parfaitement sur le web et sur 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>
  );
}
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal