4
votes

Comment écouter le changement de valeur dans React-Native-Reanimated?

J'ai créé une animation simple avec Animated de react-native avec react-native-svg .

Cela fait bien le travail,

Mais maintenant, je suis passé à react-native-reanimated reanimated parce que j'ai lu sur leur site Web que réanimé est plus rapide que Animated de react-native .

Mais ici, je suis confronté à un problème, et c'est que je ne trouve pas la fonction addListener pour écouter les changements de valeur.

Code avec Animated de react-native :

const circleRadius = new Animated.value(100);

circleRadius.addListener( circleRadius => {
       circleSVG.current.setNativeProps({ cx: circleRadius.value.toString() });
});

Comment puis-je implémenter la fonction addListener ci-dessus dans addListener react-native-reanimated ?


4 commentaires

des mises à jour à ce sujet?


Malheureusement je n'ai toujours pas pu trouver un moyen pour ça


@Muhammad Avez-vous vérifié cela? software-mansion.github.io/react-native-reanimated/...


@vishtree selon la description, cela semble être une chose différente


4 Réponses :


9
votes

Vous pouvez obtenir un comportement similaire en utilisant Animated.call . Voici un joli tutoriel sur le sujet.

Édité:

Par exemple, pour écouter les modifications de circleRadius , vous pouvez utiliser ce code:

  import { call, useCode } from 'react-native-reanimated'

  useCode(() => {
    return call([circleRadius], (circleRadius) => {
      console.log(circleRadius)
    })
  }, [circleRadius])

Est-ce que ça fait ce que tu veux?


5 commentaires

didbt fonctionne comme je veux, s'il vous plaît revoir ma question


@Muhammad désolé de l'entendre. Je vais ajouter un exemple de code minimal, peut-être que nous ne nous comprenons pas :)


Merci beaucoup, pourriez-vous s'il vous plaît me faire savoir d'où vient la fonction d' call ???


Merci beaucoup, j'obtiens cette erreur après la mise à jour de votre code: Tentative d'appeler la méthode virtuelle 'double.java.lang.Double.doubleValue ()' sur une référence d'objet nulle


Aussi je mets à jour uniquement le cx comme celui-ci circleSVG.current.setNativeProps({ cx: circleRadius.value.toString() }); alors dans votre code, qu'est-ce qui sera mis dans `cx '?



1
votes

Reanimated se veut une API déclarative qui vous permet d'exécuter des animations plus avancées et donc une logique complexe sur le thread natif.

La raison pour laquelle quelque chose de similaire à addListener n'est pas implémenté est que cela nécessiterait des messages inutiles entre le thread natif et JS. Ainsi, plutôt que d'utiliser un écouteur et setNativeProps pour mettre à jour la propriété cx de votre cercle, il serait préférable d'utiliser un AnimatedNode .

import { Circle } from 'react-native-svg';

// must make Circle compatible with Animated Values
const AnimatedCircle = Animated.createAnimatedComponent(Circle);

// then within your svg
<AnimatedCircle 
  // ... add other props
cx={circleRadius}
/>
const circleRadius = new Animated.value(100);

circleRadius.addListener( circleRadius => {
       circleSVG.current.setNativeProps({ cx: circleRadius.value.toString() });
});


2 commentaires

merci, votre code est le même que mon code, alors pourriez-vous s'il vous plaît me montrer quelle est votre solution


Pourriez-vous expliquer votre cas d'utilisation ou ajouter plus de votre code à la question? Je ne sais pas comment ou ce qui met à jour le cercle AnimatedValue



2
votes
import React, { FC, useRef } from 'react';
import { StyleSheet, TextInput, View } from 'react-native';
import Svg, { G, Circle } from 'react-native-svg';
import Animated, { call, Easing, interpolate, useCode } from 'react-native-reanimated';
import { timing } from 'react-native-redash';

interface DonutChartProps {
  percentage: number;
  radius?: number;
  strokeWidth?: number;
  duration?: number;
  color?: string;
  delay?: number;
  textColor?: string;
  max?: number;
}

const AnimatedCircle = Animated.createAnimatedComponent(Circle);
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);

const DonutChart: FC<DonutChartProps> = ({
  percentage,
  radius = 40,
  strokeWidth = 10,
  duration = 500,
  color = 'tomato',
  textColor,
  max = 100,
}) => {
  const inputRef = useRef<TextInput>(null);

  const halfCircle = radius + strokeWidth;
  const circumference = 2 * Math.PI * radius;
  const maxPercentage = (100 * percentage) / max;

  const animation = timing({
    from: 0,
    to: 1,
    duration,
    easing: Easing.inOut(Easing.linear),
  });

  const strokeDashoffset = interpolate(animation, {
    inputRange: [0, 1],
    outputRange: [circumference, circumference - (maxPercentage * circumference) / 100],
  });

  const textValue = interpolate(animation, {
    inputRange: [0, 1],
    outputRange: [0, Math.round(percentage)],
  });

  useCode(
    () => [
      call([textValue], ([textValue]) => {
        if (inputRef.current) {
          inputRef.current.setNativeProps({
            text: `${Math.round(textValue)}`,
          });
        }
      }),
    ],
    [textValue]
  );

  return (
    <View>
      <Svg width={radius * 2} height={radius * 2} viewBox={`0 0 ${halfCircle * 2} ${halfCircle * 2}`}>
        <G rotation="-90" origin={`${halfCircle}, ${halfCircle}`}>
          <Circle
            cx="50%"
            cy="50%"
            stroke={color}
            strokeWidth={strokeWidth}
            r={radius}
            fill="transparent"
            strokeOpacity={0.2}
          />
          <AnimatedCircle
            cx="50%"
            cy="50%"
            stroke={color}
            strokeWidth={strokeWidth}
            r={radius}
            fill="transparent"
            strokeDasharray={circumference}
            strokeDashoffset={strokeDashoffset}
            strokeLinecap="round"
          />
        </G>
      </Svg>
      <AnimatedTextInput
        ref={inputRef}
        underlineColorAndroid="transparent"
        editable={false}
        defaultValue="0"
        style={[
          StyleSheet.absoluteFillObject,
          { fontSize: radius / 2, color: textColor ?? color, fontWeight: '900', textAlign: 'center' },
        ]}
      />
    </View>
  );
};

export default DonutChart;


1 commentaires

comme vous pouvez le voir dans mon code, j'utilise useCode et call pour changer textValue en douceur.



0
votes

vous devez absolument utiliser useCode et call . il y a un problème lié à ceci: https://github.com/software-mansion/react-native-reanimated/issues/1417


0 commentaires