Search code examples
react-nativereact-native-reanimatedreact-native-reanimated-v2react-native-animatable

reactive animation value that not of the style type react native reanimated-2 (SVG props)


I am working with ReactNative-reanimated-2 I want to make an animation with an SVG path at color properties

I know how to do it in style properties with useAnimationStyle but how can to do that with non-style properties like SVG prpos

like that

const animatedStyleColor = useAnimatedStyle(() => {
  return {
    color: interpolate(nimatedValue.value, [0, 50], ['blue', 'red'], {
      extrapolateRight: Extrapolation.CLAMP,
    }),
  };
});

<Svg width={80} height={60} viewBox="0 0 8 4">
  <AnimatedPath
    d="M0 4l4-4 4 4"
    stroke={'blue'} //here I need to animation
    strokeWidth={3.5}
    fill="none"
    fillRule="evenodd"
    strokeLinecap="round"
    strokeLinejoin="round"
  />
</Svg>

My Demo

but is that not work how can to make that


Solution

  • I figured it out. Turns out that there's a bug/issue with useAnimatedProps that is resolved by providing an empty onPress function (here's the issue):

    import { Button, Text } from 'react-native';
    import Animated, {
      useAnimatedStyle,
      useSharedValue,
      withTiming,
      interpolate,
      useAnimatedProps,
      useDerivedValue,
      interpolateColor,
      Extrapolation,
    } from 'react-native-reanimated';
    import Svg, { Path } from 'react-native-svg';
    
    // moved out side of component to avoid recreating AnimatedPath on re-renders
    const AnimatedPath = Animated.createAnimatedComponent(Path);
    
    export default function AssetExample() {
      const animatedValue = useSharedValue(50);
      // keep track of current color and color animating to
      const targetColor = useSharedValue('#ad08ed');
      const currentColor = useSharedValue('#acc880');
      // interpolate between to colors
      const color = useDerivedValue(() => {
        return interpolateColor(
          animatedValue.value,
          [0, 50],
          [currentColor.value, targetColor.value]
        );
      });
    
      const changeColor = (newColor) => {
        targetColor.value = newColor;
        currentColor.value = color.value;
        animatedValue.value = withTiming(animatedValue.value > 0 ? 0 : 50, {
          duration: 1500,
        });
      };
      const animatedProps = useAnimatedProps(() => {
        return {
          stroke: color.value,
          strokeWidth: interpolate(animatedValue.value, [0, 50], [1.5, 3.5]),
        };
      });
    
      return (
        <>
          <Button
            onPress={() => changeColor(getRandomColor())}
            title={'Change color'}
          />
          <Svg width={100} height={100} viewBox="0 0 8 4">
            <AnimatedPath
              d="M0 4l4-4 4 4"
              strokeWidth={3.5}
              fill="none"
              fillRule="evenodd"
              strokeLinecap="round"
              strokeLinejoin="round"
              animatedProps={animatedProps}
              // found out there's a bug that is resolved by having onPress
              // https://github.com/software-mansion/react-native-reanimated/issues/3321
              onPress={() => {}}
            />
          </Svg>
        </>
      );
    }
    
    const getRandomInt = (min = 0, max = 1) => {
      const range = max - min;
      return Math.floor(Math.random() * range) + min;
    };
    
    const getRandomColor = () => {
      const rgb = [
        getRandomInt(0, 255),
        getRandomInt(0, 255),
        getRandomInt(0, 255),
      ].map((int) => int.toString(16).padStart(2, '0'));
      return '#' + rgb.join('');
    };
    

    Demo