Home > OS >  How to animate expo-linear-gradient with reanimated?
How to animate expo-linear-gradient with reanimated?

Time:01-10

I am using react-native-reanimated and want to animate the colors of my expo-linear-gradient. Unfortunately, nothing changes. I also created a Expo Snack.

import * as React from 'react';
import { View, Button } from 'react-native';
import Animated, {
  interpolateColor,
  useAnimatedProps,
  useSharedValue,
  withTiming,
} from 'react-native-reanimated';

import { LinearGradient } from 'expo-linear-gradient';

const AnimatedLinearGradient = Animated.createAnimatedComponent(LinearGradient);

export default function App() {
  const colorsValue = useSharedValue(1); 

  const animatedProps = useAnimatedProps(() => {
    return {
      colors: [
        interpolateColor(colorsValue.value, [0, 1], ['#FFFFFF', '#000000']),
        interpolateColor(colorsValue.value, [0, 1], ['#FFFFFF', '#00ff00']),
      ],
    };
  });

  return (
    <View>
      <AnimatedLinearGradient
        animatedProps={animatedProps}
        style={{ height: 400, width: '100%' }}
      />
      <Button
        title="Change colors"
        onPress={() => (colorsValue.value = withTiming(0, { duration: 2000 }))}
      />
    </View>
  );
}

Am I using animatedProps wrongly here? Any help would greatly be appreciated.

CodePudding user response:

I think it is not possible to do this with expo-linear-gradient because under the hood of this component on ios for example is CALayer and if you check reanimated docs for useAnimatedProps it says that:

Only "native" properties of "native views" can be set via useAnimatedProps. The most common usecase for this hook is when we want to animate properties of some third-party native component, since most of the properties for the core React Native components are a part of the styles anyways (at least the properties for which it makes sense to be animated). You can use the following functions to animate properties that Reanimated don't support by default:

addWhitelistedNativeProps() is used to animate properties that trigger layout recalculation, you can find them here.

addWhitelistedUIProps() is used for properties that are updated directly on the UI thread, currently allowed props are listed here.

CodePudding user response:

unfortunately, I'm not sure you can do that. You're using correctly the useAnimatedProps hook, but usually it doesn't work for all properties.

If you want to achieve this type of animation, I highly recommend you to try the LinearGradient component from @shopify/react-native-skia package.

You can easily reuse the same logic, but with the Skia values:

 const colorsValue = useSharedValue(1); 
 const skiaFirstColor = useValue(0); 
 const skiaSecondColor = useValue(0);

 useSharedValueEffect(() => {
   skiaFirstColor.current = interpolateColor(colorsValue.value, [0, 1], ['#FFFFFF', '#000000']);
   skiaSecondColor.current = interpolateColor(colorsValue.value, [0, 1], ['#FFFFFF', '#00ff00']);
 }, colorsValue); // you can pass other shared values as extra parameters

 const colors = useComputedValue(() => {
  return [skiaFirstColor.current, skiaSecondColor.current]
 }, [skiaFirstColor, skiaSecondColor])

return (<... 
  <Canvas>
    <LinearGradient colors={colors} /> 
  </Canvas>
</>)
  

Let me know if it helps.

  • Related