Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The fill and stroke props aren't animated #2561

Open
grevtsovna opened this issue Dec 3, 2024 · 2 comments
Open

The fill and stroke props aren't animated #2561

grevtsovna opened this issue Dec 3, 2024 · 2 comments

Comments

@grevtsovna
Copy link

grevtsovna commented Dec 3, 2024

Description

I've encountered some problems with animating SVG. It looks like there's a problem when I try animating stroke and fill props. Animations work fine with other props as width, height and color.

I've also tried to animate this either with or without adapter (createAnimatedPropAdapter). The result is the same.
Here's a Snack without adapter - https://snack.expo.dev/v5hIak6G8R1Sc6d4PvZXZ

Versions of react-native-reanimated I've tried - 3.15.5 and 3.16.1

Steps to reproduce

  1. Create new SharedValue
  2. Create some function to animate the SharedValue from 0 to 1 and vice versa
  3. Create animated props, which are include stroke and fill, using useAnimatedProps and apply them to a SVG element.

Snack or a link to a repository

https://snack.expo.dev/9B8O7pBATpv9u7YumqCSA?platform=android

SVG version

15.8.0

React Native version

0.74.5

Platforms

Android, iOS

JavaScript runtime

Hermes

Workflow

Expo Dev Client

Architecture

Paper (Old Architecture)

Build type

Debug app & dev bundle

Device

iOS simulator

Device model

No response

Acknowledgements

Yes

@jakex7
Copy link
Member

jakex7 commented Dec 3, 2024

Hey @grevtsovna,
You’re right — animating the fill and stroke of an SVG element isn’t straightforward at the moment due to its implementation in JS, where these props are passed to the Group. However, there’s a simple workaround for this. You can wrap all the elements inside the <Svg> tag with a <G> tag, or more specifically, use AnimatedG. Then, you can pass the animated props directly to the group element. Here’s a quick example:

const AnimatedSvg = Animated.createAnimatedComponent(Svg);
const AnimatedG = Animated.createAnimatedComponent(G);
function Example() {
  const sv = useSharedValue(0);
  const runAnimation = () => { sv.value = withTiming(sv.value ? 0 : 1) };

  const animatedSvgProps = useAnimatedProps(() => {
    return {
      width: interpolate(sv.value, [0, 1], [50, 100], Extrapolation.CLAMP),
      height: interpolate(sv.value, [0, 1], [50, 100], Extrapolation.CLAMP),
    };
  });
  const animatedGProps = useAnimatedProps(() => {
    return {
      color: interpolateColor(sv.value, [0, 1], ['blue', 'violet']),
      fill: interpolateColor(
        sv.value,
        [0, 1],
        ['rgb(255,0,0)', 'rgb(0,255,0)'],
      ),
      stroke: interpolateColor(
        sv.value,
        [0, 1],
        ['rgb(0,0,255)', 'rgb(255,0,0)'],
      ),
    };
  });

  return (
    <>
      <AnimatedSvg viewBox="-16 -16 544 544" animatedProps={animatedSvgProps}>
        <AnimatedG animatedProps={animatedGProps}>
          <Path
            d="M318.37,85.45L422.53,190.11,158.89,455,54.79,350.38ZM501.56,60.2L455.11,13.53a45.93,45.93,0,0,0-65.11,0L345.51,58.24,449.66,162.9l51.9-52.15A35.8,35.8,0,0,0,501.56,60.2ZM0.29,497.49a11.88,11.88,0,0,0,14.34,14.17l116.06-28.28L26.59,378.72Z"
            strokeWidth="32"
          />
          <Path d="M0,0L512,512" stroke="currentColor" strokeWidth="32" />
          <Path d="M512,0L0,512" stroke="currentColor" strokeWidth="32" />
        </AnimatedG>
      </AnimatedSvg>
      <Button title="Run Animation" onPress={runAnimation} />
    </>
  );
}

@grevtsovna
Copy link
Author

Hi @jakex7,
Thank you for sharing the workaround.

However, I should mention that it might not be easy to apply in some cases. For example, initially, I faced the issue when I was trying to animate an icon from @tabler/icons-react-native. As it has its own implementation of creating SVG elements, it seems to me I can't add the wrapper directly. Anyway, it must be possible via some patch, I guess. I'll try it later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants