Javascript 如何倾听《重生》中的价值观变化?

Javascript 如何倾听《重生》中的价值观变化?,javascript,react-native,react-native-svg,react-native-reanimated,Javascript,React Native,React Native Svg,React Native Reanimated,我用react native和react native svg创建了一个简单的动画 这项工作做得很好 但现在我切换到了react native reanimated,因为我在他们的网站上看到,reanimated比Animated的react native快 但是在这里我遇到了一个问题,那就是我找不到函数addListener来监听值的变化 使用本机中的动画编码: const circleRadius = new Animated.value(100); circleRadius.addLis

我用
react native
react native svg
创建了一个简单的动画

这项工作做得很好

但现在我切换到了
react native reanimated
,因为我在他们的网站上看到,reanimated比
Animated
react native

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

使用本机中的动画编码:

const circleRadius = new Animated.value(100);

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

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

没有实现类似于
addListener
的东西的原因是,它需要在本机线程和JS线程之间发送不必要的消息。因此,最好使用
AnimatedNode
,而不是使用侦听器和
setNativeProps
来更新圆的
cx
属性

从'react native svg'导入{Circle};
//必须使圆与动画值兼容
const AnimatedCircle=Animated.createAnimatedComponent(圆);
//然后在svg中
从“React”导入React,{FC,useRef};
从“react native”导入{StyleSheet,TextInput,View};
从“react native Svg”导入Svg,{G,Circle};
从“react native reanimated”导入动画,{call,Easing,interpolate,useCode};
从“react native redash”导入{timing};
接口DonutChartProps{
百分比:数字;
半径?:数字;
冲程宽度?:编号;
持续时间?:数字;
颜色?:字符串;
延迟?:数字;
textColor?:字符串;
最大?:数字;
}
const AnimatedCircle=Animated.createAnimatedComponent(圆);
const animatedteddeput=Animated.createAnimatedComponent(TextInput);
常数DonutChart:FC=({
百分比,
半径=40,
冲程宽度=10,
持续时间=500,
颜色=‘番茄’,
textColor,
最大值=100,
}) => {
const inputRef=useRef(null);
常数半圆=半径+冲程宽度;
常数周长=2*Math.PI*半径;
常量最大百分比=(100*百分比)/最大值;
常量动画=计时({
起:0,,
致:1,,
期间
放松:放松.inOut(放松.linear),
});
常量strokeDashoffset=插值(动画{
输入范围:[0,1],
输出范围:[周长,周长-(最大百分比*周长)/100],
});
const textValue=插值(动画{
输入范围:[0,1],
输出范围:[0,数学四舍五入(百分比)],
});
使用代码(
() => [
调用([textValue],([textValue])=>{
if(输入参考电流){
inputRef.current.setNativeProps({
text:`${Math.round(textValue)}`,
});
}
}),
],
[文本值]
);
返回(
);
};
导出默认DonutChart;

这方面有什么更新吗?不幸的是,我仍然找不到解决问题的方法that@Muhammad你检查过这个了吗@vishtree根据描述,这似乎是另一件我想要的东西,请再次查看我的question@Muhammad很遗憾听到这个消息。我将添加一个最小的代码示例,可能我们彼此不了解:)非常感谢,您能告诉我
调用
函数的来源吗???非常感谢,我在更新为您的代码后遇到此错误:尝试调用虚拟方法'double.java.lang.double.doubleValue()'在空对象引用上,我只更新
cx
,如下
circleSVG.current.setNativeProps({cx:circleRadius.value.toString())那么在您的代码中,“cx”将包含哪些内容?谢谢,您的代码与我的代码相同,因此,您可以向我展示您的解决方案吗?您可以详细说明您的用例,或者在问题中添加更多的代码吗?我不确定如何或是什么在更新动画值循环正如您在我的代码中看到的那样,我使用
useCode
call
平滑地更改textValue。如何使用复活的V2:(?
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}
/>
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;