software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
8.87k stars 1.3k forks source link

Impossible to animate any SVG color on android #6080

Closed noah-blanchard closed 3 months ago

noah-blanchard commented 3 months ago

Description

Any color, fill color, stroke color... on an SVG don't get updated, on ANDROID specifically

Expected behavour

Update the color of the stroke or fill when pressing the button

Steps to reproduce

const AnimatedCircle = Animated.createAnimatedComponent(Circle);

export default function AnimCircle() {
  const sh = useSharedValue(10);

  const handlePress = () => {
    sh.value += 10;
  };

  const animatedProps = useAnimatedProps(() => {
    console.log(interpolateColor(sh.value % 30, [0, 10, 20], ['rgb(255,0,0)', 'rgb(0,255,0)', 'rgb(0,0,255)']));
    return { r: 50, stroke: interpolateColor(sh.value % 30, [0, 10, 20], ['blue', 'red', 'green']) };
  });

  return (
    <View style={styles.container}>
      <Svg style={styles.svg}>
        <AnimatedCircle cx="50%" cy="50%" strokeWidth={10} animatedProps={animatedProps} />
      </Svg>
      <Button onPress={handlePress}>Press me !</Button>
    </View>
  );
}

Here's the log result :

 LOG  -65536
 LOG  -16711936
 LOG  -16776961
 LOG  -65536
 LOG  -16711936
 LOG  -16776961
 LOG  -65536
 LOG  -16711936
 LOG  -16776961
 LOG  -65536
 LOG  -16711936
 LOG  -16776961
 LOG  -65536
 LOG  -16711936
 LOG  -16776961
 LOG  -65536
 LOG  -16711936
 LOG  -16776961
 LOG  -65536
 LOG  -16711936
 LOG  -16776961
 LOG  -65536
 LOG  -16711936

Similar issues

I found some similar issues stating I should use RGB colors, I tried all I could try but I'm still having exactly the same problem unfortunately.

Everything's works perfectly on my web browser, but never on my phone. I'm using storybook and expo.

Snack or a link to a repository

https://snack.expo.dev/4HWDed_sqs1LuhrMgL8aX

Reanimated version

3.6.2

React Native version

0.68.7

Platforms

Android, Web

JavaScript runtime

None

Workflow

None

Architecture

None

Build type

None

Device

None

Device model

No response

Acknowledgements

Yes

Martinocom commented 3 months ago

Have you tried it with an adapter? https://docs.swmansion.com/react-native-reanimated/docs/core/useAnimatedProps/#adapters-

szydlovsky commented 3 months ago

hey @noah-blanchard, just as @Martinocom mentioned, animated prop adapter is the way to go for you. I have added the adapter to your example to make it work:

import React from 'react';
import { View, Button, StyleSheet } from 'react-native';
import { Svg, Circle } from 'react-native-svg';
import Animated, {
  interpolateColor,
  useSharedValue,
  useAnimatedProps,
  createAnimatedPropAdapter,
  processColor,
} from 'react-native-reanimated';

const AnimatedCircle = Animated.createAnimatedComponent(Circle);

const strokeAdapter = createAnimatedPropAdapter(
  (props) => {
    if (Object.keys(props).includes('stroke')) {
      props.stroke = { type: 0, payload: processColor(props.stroke) };
    }
  },
  ['stroke']
);

export default function AnimCircle() {
  const sh = useSharedValue(10);

  const handlePress = () => {
    sh.value += 10;
  };

  const animatedProps = useAnimatedProps(
    () => {
      return {
        r: 50,
        stroke: interpolateColor(
          sh.value % 30,
          [0, 10, 20],
          ['blue', 'red', 'green']
        ),
      };
    },
    null,
    strokeAdapter
  );

  return (
    <View style={styles.container}>
      <Svg style={styles.svg}>
        <AnimatedCircle
          cx="50%"
          cy="50%"
          strokeWidth={10}
          animatedProps={animatedProps}
        />
      </Svg>
      <Button title={'Press me!'} onPress={handlePress} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  svg: {
    width: 200,
    height: 200,
  },
});
noah-blanchard commented 3 months ago

hey @szydlovsky indeed it is working fine on android now, but not anymore on my browser ! This fixed the android issue, but now a new issue appeared on browser...

szydlovsky commented 3 months ago

@noah-blanchard then it is strightforward: add a platform check when passing adapter argument; for web null, otherwise the adapter

noah-blanchard commented 3 months ago

@noah-blanchard then it is strightforward: add a platform check when passing adapter argument; for web null, otherwise the adapter

I'll do this, thanks