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 Réponses :
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?
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 '?
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() }); });
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
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;
comme vous pouvez le voir dans mon code, j'utilise useCode
et call
pour changer textValue en douceur.
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
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