如何倾听反应原生复活中的价值变化?



我用react-nativereact-native-svgAnimated创建了一个简单的动画。

这做得很好,

但是现在我切换到我在他们的网站上读到react-native-reanimated因为复活比react-nativeAnimated更快.

但是在这里我遇到了一个问题,那就是我找不到函数addListener来监听值的变化。

使用来自react-nativeAnimated的代码:

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

如何在react-native-reanimated中实现上述addListener功能

您可以使用Animated.call实现类似的行为。这是一个关于这个主题的很好的教程。

编辑:

例如,要侦听circleRadius更改,可以使用以下代码:

import { call, useCode } from 'react-native-reanimated'
useCode(() => {
return call([circleRadius], (circleRadius) => {
console.log(circleRadius)
})
}, [circleRadius])

它能做你想做的事吗?

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;

Realive是一个声明性API,允许您在本机线程上运行更高级的动画,从而运行复杂的逻辑。

未实现类似于addListener的东西的原因是因为它需要在本机线程和JS线程之间产生不必要的消息。因此,与其使用侦听器和setNativeProps来更新圈子的cx属性,不如使用AnimatedNode.

const circleRadius = new Animated.value(100);
circleRadius.addListener( circleRadius => {
circleSVG.current.setNativeProps({ cx: circleRadius.value.toString() });
});
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}
/>

最新更新