0

我有一个反应功能组件Svg被用作底部标签栏的图标。在路线改变时,电流state.index与路线进行比较index。本质上是布尔状态的结果isFocused被传递给 Svg。

我正在尝试根据此状态为 Svg 设置动画,并且无法使用 reanimated 完成简单的操作。我最确定 fill 的值没有在useAnimatedPropshook 中更新,但我缺乏对 reanimated 有深入了解的经验。任何帮助将不胜感激

import Animated, {
  useAnimatedProps,
  useSharedValue,
} from 'react-native-reanimated';
import Svg, { Circle, Path } from 'react-native-svg';

const AnimatedSvg = Animated.createAnimatedComponent(Svg);

export default ({ isFocused }) => {
  const fill = useSharedValue({ fill: 'transparent' });
  const animatedProps = useAnimatedProps(() => {
    isFocused
      ? (fill.value = { fill: 'red' })
      : (fill.value = { fill: 'transparent' });

    return fill.value;
  });
  return (
    <AnimatedSvg
      xmlns="http://www.w3.org/2000/svg"
      width={24}
      height={24}
      animatedProps={animatedProps}
      stroke={'white'}
      strokeWidth={2}
      strokeLinecap="round"
      strokeLinejoin="round"
      className="feather feather-search">
      <Circle cx={11} cy={11} r={8} />
      <Path d="m21 21-4.35-4.35" />
    </AnimatedSvg>
  );
};
4

1 回答 1

3

更常见的方法是使用“进度变量”作为共享值。

const fillProgress = useSharedValue(isFocused? 1 : 0);

您将使用此进度变量来生成动画道具。请注意使用interpolateColor来获得实际的插值颜色。

const animatedProps = useAnimatedProps(() => {
    const fillValue = interpolateColor(fillProgress.value, [0, 1], ["transparent", "red"]);  
    return {
        fill: fillValue
    }
});

您必须返回一个具有您想要动画的属性的对象。例如,如果您想为填充和不透明度设置动画,您将返回{fill: "", opacity: -1}适当的值而不是""and -1。最后你必须制作你想要动画的实际元素。在这种情况下,您要为 Animated 设置动画Circle,而不是Svg必须为 Animated 对象的 the。

const AnimatedCircle = Animated.createAnimatedComponent(Circle);

useEffect然后,您可以使用相应的动画来检测是否被聚焦。

useEffect(() => {
    fillProgress.value = withTiming(isFocused? 1 : 0);
}, [isFocused]);

fillProgress记得像在withTiming函数中一样设置初始值。

总而言之,您必须为使用动画属性的元素设置动画,并且您应该使用上面提到的进度变量。

这是完整的修改代码(在 Android 上测试):

import Animated, {
    useAnimatedProps,
    useSharedValue,
} from 'react-native-reanimated';
import Svg, { Circle, Path } from 'react-native-svg';

const AnimatedCircle = Animated.createAnimatedComponent(Circle);

export default function Icon ({ isFocused }) {
    const fillProgress = useSharedValue(isFocused? 1 : 0);
    const animatedProps = useAnimatedProps(() => {
        const fillValue = interpolateColor(fillProgress.value, [0, 1], ["transparent", "red"]);  
        return {
            fill: fillValue
        }
    });


    useEffect(() => {
        fillProgress.value = withTiming(isFocused? 1 : 0);
    }, [isFocused]);

    return (
      <Svg
        width={24}
        height={24}
        stroke={'white'}
        strokeWidth={2}
        strokeLinecap="round"
        strokeLinejoin="round"
        className="feather feather-search">
            <AnimatedCircle animatedProps={animatedProps} cx={11} cy={11} r={8} />
            <Path d="m21 21-4.35-4.35" />
      </Svg>
    );
};
于 2021-12-31T09:06:50.980 回答