React Native Reanimated: A Deep Dive

React Native Reanimated: A Deep Dive
user avatar

Evan Marie Carr

June 05, 2024

Summary:

Explore the powerful capabilities of React Native Reanimated: smooth and complex animations, manage gestures, and enhance your user interface with movement, text animations, keyframes, and scroll-triggered effects

App Design

Mobile Apps

React Native

Expo

React Native Reanimated is a powerful library for creating smooth and complex animations in React Native applications. It uses native threads for performance, providing a declarative API for animations and gestures. Here, we will explore various features and functionalities of React Native Reanimated, and I will offer detailed explanations and examples.

Key features of React Native Reanimated:

Native Performance: Reanimated uses the power of the native UI thread, allowing animations to run smoothly and efficiently without blocking the JavaScript thread.

Declarative API: Reanimated provides a declarative API for defining animations and gestures, making it easier to reason about and maintain your animation logic.

Gesture Handling: Reanimated includes a gesture system that enables you to handle complex touch interactions, such as pan, pinch, and rotate, with ease.

Shared Values: Reanimated introduces the concept of shared values, which allow you to create dependencies between animated values and update them synchronously.

Worklets: Worklets are small, isolated JavaScript functions that run on the UI thread, enabling you to perform complex calculations and logic without impacting performance.

Animations: Reanimated provides a wide range of animation primitives, such as timing, spring, and decay animations, along with more advanced concepts like keyframes and composition.

Layout Animations: Reanimated supports layout animations, allowing you to animate the position and size of components when the layout changes.

Reanimated 3

Reanimated 3 is the latest version of the React Native Reanimated library, offering enhanced performance, new features, and improved ease of use for creating complex animations in React Native applications.

Highlights introduced in Reanimated 3:

Improved Performance - Reanimated 3 further optimizes animations by leveraging the native thread, ensuring smooth and responsive animations even under heavy load.

Simplified API - The API has been streamlined to make it easier to use and more intuitive. This includes more straightforward hooks and functions for common animation tasks.

Enhanced Gesture Handling - Integration with react-native-gesture-handler has been improved, providing more robust and flexible gesture handling capabilities. This makes it easier to create interactive and responsive UIs.

New Animation Types - Reanimated 3 introduces new types of animations, allowing for more creative and diverse animation effects. These include advanced keyframe animations and more sophisticated timing functions.

Better Interoperability - Improved compatibility with other React Native libraries and components, making it easier to integrate Reanimated animations into existing projects.

Developer Experience - Enhanced debugging and development tools, providing better visibility into animations and easier troubleshooting. This includes improved logging and error messages.

Community and Support - Stronger community support and more comprehensive documentation, making it easier for developers to get started and find solutions to common issues.

Shared Values:

Core to Reanimated, shared values allow you to define and animate state variables that run on the UI thread for better performance.

const offsetX = useSharedValue(0);

Animated Styles

Hooks like useAnimatedStyle enable you to create styles that update automatically in response to shared value changes.

const animatedStyle = useAnimatedStyle(() => ({
  transform: [{ translateX: offsetX.value }],
}));

Gesture Handling

Seamless integration with react-native-gesture-handler allows for creating complex gesture-driven animations.

const gesture = Gesture.Pan().onUpdate((event) => {
  offsetX.value = event.translationX;
});

Animation Functions

New and improved functions like withSpring, withTiming, and withDecay offer a variety of ways to animate properties.

offsetX.value = withSpring(100);

Animating Movements Along the X and Y Axis

Animating elements along the x and y axes is a fundamental aspect of creating dynamic interfaces. Reanimated provides a straightforward way to handle these animations using shared values and animated styles.

Key Concepts:

useSharedValue: This hook creates a shared value that can be animated.

useAnimatedStyle: This hook creates an animated style that reacts to changes in shared values.

Animation Functions: Functions like withSpring, withTiming, and withDecay define the type of animation.

Animation Examples and Explanations

Example One: X & Y Animations

This example demonstrates the basic use of React Native Reanimated for animating elements along the x and y axes. This component provides interactive buttons to move a square element in different directions using spring animations. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create shared values (offsetX and offsetY) which represent the x and y positions of the animated element. These values are essential for tracking and updating the element's position during animations.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared values. The style transforms the element by translating it along the x and y axes according to offsetX and offsetY.
  • Spring Animation: The withSpring function is used to animate the shared values with a spring effect, providing a smooth and natural animation.

Component Structure

  • Shared Values Initialization:
    const offsetX = useSharedValue(0);
    const offsetY = useSharedValue(0);
    These lines initialize the shared values offsetX and offsetY to zero.
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => {
      return {
        transform: [{ translateX: offsetX.value }, { translateY: offsetY.value }],
      };
    });
    This hook creates an animated style that updates the element's transform property based on the current values of offsetX and offsetY.
  • Utility Functions:
    • Random Sign Generator: Generates a random sign (-1 or 1) to randomly determine the direction of movement.
      const getRandomSign = () => {
        return Math.random() < 0.5 ? -1 : 1;
      };
    • Reset Animation: Resets the element's position to the origin (0, 0) using a spring animation.
      const resetAnimation = () => {
        offsetX.value = withSpring(0);
        offsetY.value = withSpring(0);
      };
  • Rendering the Component:
    return (
      <AnimationContainer resetAnimation={resetAnimation} title="X & Y Animations">
        <Animated.View
          style={[
            animatedElementStyle,
            animatedStyles,
            { width: 40, height: 40 },
          ]}
        />
        <Flex style={{ gap: 20 }}>
          <MyButton
            text="Move Y"
            onPress={() => {
              offsetY.value = withSpring(Math.random() * -200);
            }}
          />
          <MyButton
            text="Move X"
            onPress={() => {
              const randomValue = Math.random() * 200;
              const randomSign = getRandomSign();
              offsetX.value = withSpring(randomValue * randomSign);
            }}
          />
          <MyButton
            text="Move X & Y"
            onPress={() => {
              const randomValueX = Math.random() * 200;
              const randomValueY = Math.random() * -200;
              const randomSignX = getRandomSign();
              const randomSignY = getRandomSign();
              offsetX.value = withSpring(randomValueX * randomSignX);
              offsetY.value = withSpring(randomValueY * randomSignY);
            }}
          />
        </Flex>
      </AnimationContainer>
    );
    The component renders an animated view styled with both static and animated styles, representing a square that moves based on user interactions.

Example Two: Animation with Timing

Example Two showcases the use of React Native Reanimated for creating timed animations. This component allows an element to move along the x-axis with a smooth timing animation when a button is pressed. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create a shared value (offset) which represents the x position of the animated element. This value is essential for tracking and updating the element's position during animations.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared value. The style transforms the element by translating it along the x-axis according to offset.
  • Timing Animation: The withTiming function is used to animate the shared value with a timed effect, providing a smooth and controlled animation.

Component Structure

  • Shared Values Initialization:
    const offset = useSharedValue(-150);
    This line initializes the shared value offset to -150.
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => {
      return {
        transform: [{ translateX: offset.value }],
      };
    });
    This hook creates an animated style that updates the element's transform property based on the current value of offset.
  • Reset Animation: Resets the element's position to the initial state (-150).
    const resetAnimation = () => {
      offset.value = -150;
    };
  • Rendering the Component:
    return (
      <AnimationContainer resetAnimation={resetAnimation} height={screenHeight * 0.25} title="Animation with Timing">
        <Animated.View
          style={[
            animatedStyles,
            animatedElementStyle,
            { width: 80, height: 80 },
          ]}
        />
        <MyButton
          text="Move with Timing"
          onPress={() => {
            offset.value = withTiming(400, { duration: 1000 });
          }}
        />
      </AnimationContainer>
    );
    The component renders an animated view styled with both static and animated styles, representing a rectangle that moves based on user interactions.

Gesture-Based Animations

Gestures play a crucial role in creating interactive and responsive UIs. React Native Reanimated, combined with react-native-gesture-handler, allows for complex gesture-based animations.

Key Concepts:

Gesture Handlers: Handling gestures like pan, pinch, and tap.

Gesture State Management: Managing the state and response of gestures

Composed Gestures: Combining multiple gestures for complex interactions

Example Three: Gesture Animation

Example Three demonstrates the use of React Native Reanimated in combination with gesture handling to create interactive animations. This component allows an element to be dragged around the screen, snapping back to its original position with a spring animation when released. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create shared values (offsetX, offsetY, startX, and startY) which represent the x and y positions of the animated element. These values are essential for tracking and updating the element's position during gestures.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared values. The style transforms the element by translating it along the x and y axes according to offsetX and offsetY.
  • Gesture Handling: The Gesture API from react-native-gesture-handler is used to handle pan gestures, allowing the element to be dragged around the screen.
  • Spring Animation: The withSpring function is used to animate the shared values with a spring effect, providing a smooth and natural animation when the gesture ends.

Component Structure

  • Shared Values Initialization:
    const offsetX = useSharedValue(0);
    const offsetY = useSharedValue(0);
    const startX = useSharedValue(0);
    const startY = useSharedValue(0);
    These lines initialize the shared values to zero.
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => {
      return {
        transform: [{ translateX: offsetX.value }, { translateY: offsetY.value }],
      };
    });
    This hook creates an animated style that updates the element's transform property based on the current values of offsetX and offsetY.
  • Gesture Handling: Using the Gesture.Pan() API to handle drag gestures.
    const gesture = Gesture.Pan()
      .onStart(() => {
        cancelAnimation(offsetX);
        cancelAnimation(offsetY);
        startX.value = offsetX.value;
        startY.value = offsetY.value;
      })
      .onUpdate((event) => {
        offsetX.value = startX.value + event.translationX;
        offsetY.value = startY.value + event.translationY;
      })
      .onEnd(() => {
        offsetX.value = withSpring(0);
        offsetY.value = withSpring(0);
      });
    • onStart: Cancels any ongoing animations and stores the starting position of the gesture.
    • onUpdate: Updates the offsetX and offsetY values based on the gesture's translation.
    • onEnd: Animates the element back to its original position using a spring animation.
  • Rendering the Component:
    return (
      <AnimationContainer title="Spring Physics Gesture" headingLight>
        <FlexFull style={{ height: "100%", justifyContent: "center", alignItems: "center" }}>
          <GestureDetector gesture={gesture}>
            <Animated.View
              style={[
                animatedStyles,
                elementStyleTwo,
                { width: 60, height: 60, justifyContent: "center" },
              ]}
            >
              <TextXs style={{ textAlign: "center", fontWeight: 600 }}>Drag Me</TextXs>
            </Animated.View>
          </GestureDetector>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated view styled with both static and animated styles, representing a draggable element. The text inside the element indicates that it can be dragged.

Example Four: Gesture Handling with Decay

Example Four demonstrates the use of React Native Reanimated in combination with gesture handling to create interactive animations. This component allows an element to be dragged around the screen and flung with a decay animation when released. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create shared values (offsetX, offsetY, startX, and startY) which represent the x and y positions of the animated element. These values are essential for tracking and updating the element's position during gestures.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared values. The style transforms the element by translating it along the x and y axes according to offsetX and offsetY.
  • Gesture Handling: The Gesture API from react-native-gesture-handler is used to handle pan gestures, allowing the element to be dragged around the screen.
  • Decay Animation: The withDecay function is used to animate the shared values with a decay effect, providing a smooth and natural animation when the gesture ends.

Component Structure

  • Shared Values Initialization:
    const offsetX = useSharedValue(0);
    const offsetY = useSharedValue(0);
    const startX = useSharedValue(0);
    const startY = useSharedValue(0);
    These lines initialize the shared values to zero.
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => {
      return {
        transform: [{ translateX: offsetX.value }, { translateY: offsetY.value }],
      };
    });
    This hook creates an animated style that updates the element's transform property based on the current values of offsetX and offsetY.
  • Gesture Handling: Using the Gesture.Pan() API to handle drag gestures.
    const gesture = Gesture.Pan()
      .onStart(() => {
        cancelAnimation(offsetX);
        cancelAnimation(offsetY);
        startX.value = offsetX.value;
        startY.value = offsetY.value;
      })
      .onUpdate((event) => {
        offsetX.value = startX.value + event.translationX;
        offsetY.value = startY.value + event.translationY;
      })
      .onEnd((event) => {
        offsetX.value = withDecay({
          velocity: event.velocityX,
          deceleration: 0.998,
        });
        offsetY.value = withDecay({
          velocity: event.velocityY,
          deceleration: 0.998,
        });
      });
    • onStart: Cancels any ongoing animations and stores the starting position of the gesture.
    • onUpdate: Updates the offsetX and offsetY values based on the gesture's translation.
    • onEnd: Animates the element with a decay effect based on the gesture's velocity.
  • Reset Animation: Resets the element's position to the origin (0, 0).
    const resetAnimation = () => {
      offsetX.value = 0;
      offsetY.value = 0;
    };
  • Rendering the Component:
    return (
      <AnimationContainer resetAnimation={resetAnimation} title="Gesture Handling with Decay" headingLight>
        <FlexFull style={{ height: "100%", justifyContent: "center", alignItems: "center" }}>
          <GestureDetector gesture={gesture}>
            <Animated.View
              style={[
                animatedStyles,
                elementStyleTwo,
                { width: 60, height: 60, justifyContent: "center" },
              ]}
            >
              <TextXs style={{ textAlign: "center", fontWeight: 600 }}>Fling Me</TextXs>
            </Animated.View>
          </GestureDetector>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated view styled with both static and animated styles, representing a draggable element. The text inside the element indicates that it can be flung.

Example Five: Gesture Based Animation Sequence

Example Five demonstrates the use of React Native Reanimated in combination with gesture handling to create interactive animations. This component allows an element to be dragged and scaled using pan and pinch gestures, respectively. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create shared values (offsetX, offsetY, scale, startX, startY, and startScale) which represent the x, y positions, and scale of the animated element. These values are essential for tracking and updating the element's position and scale during gestures.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared values. The style transforms the element by translating it along the x and y axes and scaling it according to offsetX, offsetY, and scale.
  • Gesture Handling: The Gesture API from react-native-gesture-handler is used to handle pan and pinch gestures, allowing the element to be dragged and scaled.
  • Spring Animation: The withSpring function is used to animate the shared values with a spring effect, providing a smooth and natural animation when the gestures end.

Component Structure

  • Shared Values Initialization:
    const offsetX = useSharedValue(0);
    const offsetY = useSharedValue(0);
    const scale = useSharedValue(1);
    const startX = useSharedValue(0);
    const startY = useSharedValue(0);
    const startScale = useSharedValue(1);
    These lines initialize the shared values to their default states.
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => {
      return {
        transform: [
          { translateX: offsetX.value },
          { translateY: offsetY.value },
          { scale: scale.value },
        ],
      };
    });
    This hook creates an animated style that updates the element's transform property based on the current values of offsetX, offsetY, and scale.
  • Gesture Handling: Using the Gesture.Pan() and Gesture.Pinch() APIs to handle drag and scale gestures.
    const panGesture = Gesture.Pan()
      .onStart(() => {
        cancelAnimation(offsetX);
        cancelAnimation(offsetY);
        startX.value = offsetX.value;
        startY.value = offsetY.value;
      })
      .onUpdate((event) => {
        offsetX.value = startX.value + event.translationX;
        offsetY.value = startY.value + event.translationY;
      })
      .onEnd(() => {
        offsetX.value = withSpring(0);
        offsetY.value = withSpring(0);
      });
    
    const pinchGesture = Gesture.Pinch()
      .onStart(() => {
        cancelAnimation(scale);
        startScale.value = scale.value;
      })
      .onUpdate((event) => {
        scale.value = startScale.value * event.scale;
      })
      .onEnd(() => {
        scale.value = withSpring(1);
      });
    
    const composedGesture = Gesture.Simultaneous(panGesture, pinchGesture);
    • Pan Gesture: Handles the drag gesture.
      • onStart: Cancels any ongoing animations and stores the starting position of the gesture.
      • onUpdate: Updates the offsetX and offsetY values based on the gesture's translation.
      • onEnd: Animates the element back to its original position using a spring animation.
    • Pinch Gesture: Handles the scale gesture.
      • onStart: Cancels any ongoing animations and stores the starting scale of the gesture.
      • onUpdate: Updates the scale value based on the gesture's scale.
      • onEnd: Animates the element back to its original scale using a spring animation.
    • Composed Gesture: Combines the pan and pinch gestures to allow simultaneous dragging and scaling.
  • Rendering the Component:
    return (
      <AnimationContainer title="Gesture Based Sequence" headingLight>
        <FlexFull style={{ height: "100%", justifyContent: "center", alignItems: "center" }}>
          <GestureDetector gesture={composedGesture}>
            <Animated.View
              style={[
                elementStyleTwo,
                animatedStyles,
                { width: 100, height: 100 },
              ]}
            />
          </GestureDetector>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated view styled with both static and animated styles, representing an element that can be dragged and scaled.

Text Animations

Animating text can enhance user experience by drawing attention or providing feedback. Reanimated offers various ways to animate text properties such as opacity, color, and scale.

Key Concepts:

Text Property Animations: Animating properties like opacity, color, and transform.

Combination of Animations: Combining multiple animations for complex effects.

Using Hooks and Styles: Leveraging useSharedValue and useAnimatedStyle for text animations.

Example Six: Sliding Text Animation

Example Six demonstrates the use of React Native Reanimated to create a sliding text animation. This component slides a text element from the left to the center of the screen using a timing animation. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create a shared value (translateX) which represents the x position of the animated text element. This value is essential for tracking and updating the element's position during the animation.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared value. The style transforms the element by translating it along the x-axis according to translateX.
  • Timing Animation: The withTiming function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.
  • Effect Hook: The useEffect hook is used to trigger the animation when the component mounts.

Component Structure

  • Shared Values Initialization:
    const translateX = useSharedValue(-350);
    This line initializes the shared value translateX to -350, starting the text element off-screen to the left.
  • Effect Hook: The useEffect hook triggers the animation when the component mounts.
    useEffect(() => {
      translateX.value = withTiming(0, { duration: 2000 });
    }, []);
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => ({
      transform: [{ translateX: translateX.value }],
    }));
    This hook creates an animated style that updates the element's transform property based on the current value of translateX.
  • Restart Animation: Function to restart the animation by resetting and reanimating the translateX value.
    const restartAnimation = () => {
      translateX.value = -350;
      translateX.value = withTiming(0, { duration: 2000 });
    };
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.2}
        title="Sliding Text"
        resetAnimation={restartAnimation}
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Animated.Text
            style={[
              animatedStyles,
              textShadows.glow200Sm,
              { fontFamily: "Play-Bold", fontSize: 33 },
            ]}
          >
            Slide to the right!
          </Animated.Text>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated text element styled with both static and animated styles, representing text that slides in from the left.

Example Seven: Color Shifting Text

Example Seven demonstrates the use of React Native Reanimated to create a color-shifting text animation. This component changes the color of a text element in a looping sequence using timing and repeat animations. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create a shared value (color) which represents the color transition state of the animated text element. This value is essential for tracking and updating the element's color during the animation.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared value. The style interpolates the color based on the value of color.
  • Timing and Repeat Animations: The withTiming function is used to animate the shared value with a timing effect, and withRepeat is used to repeat the animation indefinitely.
  • Effect Hook: The useEffect hook is used to trigger the animation when the component mounts.
  • Interpolate Color: The interpolateColor function is used to interpolate the color values based on the shared value.

Component Structure

  • Shared Values Initialization:
    const color = useSharedValue(0);
    This line initializes the shared value color to 0.
  • Effect Hook: The useEffect hook triggers the color-shifting animation when the component mounts.
    useEffect(() => {
      color.value = withRepeat(withTiming(1, { duration: 7000 }), -1, true);
    }, []);
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => {
      const textColor = interpolateColor(
        color.value,
        [0, 0.14, 0.28, 0.42, 0.56, 0.7, 0.84, 1],
        [
          col[200],
          col[300],
          col[400],
          col[500],
          col[600],
          col[700],
          col[800],
          col[900],
        ]
      );
      return { color: textColor };
    });
    This hook creates an animated style that updates the element's color based on the interpolated value of color.
  • Restart Animation: Function to restart the animation by resetting and reanimating the color value.
    const restartAnimation = () => {
      cancelAnimation(color);
      color.value = 0;
      color.value = withRepeat(withTiming(1, { duration: 7000 }), -1, true);
    };
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.2}
        title="Color Shifting Text"
        resetAnimation={restartAnimation}
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Animated.Text
            style={[
              animatedStyles,
              textShadows.glow200Sm,
              { fontFamily: "Play-Bold", fontSize: 33 },
            ]}
          >
            Color shifting
          </Animated.Text>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated text element styled with both static and animated styles, representing text that changes color in a looping sequence.

Example Eight: Rotating Text Animation

Example Eight demonstrates the use of React Native Reanimated to create a rotating text animation. This component rotates a text element 360 degrees using a timing animation. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create a shared value (rotation) which represents the rotation angle of the animated text element. This value is essential for tracking and updating the element's rotation during the animation.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared value. The style transforms the element by rotating it according to rotation.
  • Timing Animation: The withTiming function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.
  • Effect Hook: The useEffect hook is used to trigger the animation when the component mounts.

Component Structure

  • Shared Values Initialization:
    const rotation = useSharedValue(0);
    This line initializes the shared value rotation to 0.
  • Effect Hook: The useEffect hook triggers the animation when the component mounts.
    useEffect(() => {
      rotation.value = withTiming(360, { duration: 2000 });
    }, []);
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => ({
      transform: [{ rotate: `${rotation.value}deg` }],
    }));
    This hook creates an animated style that updates the element's transform property based on the current value of rotation.
  • Restart Animation: Function to restart the animation by resetting and reanimating the rotation value.
    const restartAnimation = () => {
      rotation.value = 0;
      rotation.value = withTiming(360, { duration: 2000 });
    };
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.3}
        title="Rotating Text"
        resetAnimation={restartAnimation}
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Animated.Text
            style={[
              animatedStyles,
              textShadows.glow200Sm,
              { fontFamily: "Play-Bold", fontSize: 33 },
            ]}
          >
            Rotating Text
          </Animated.Text>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated text element styled with both static and animated styles, representing text that rotates 360 degrees.

Example Nine: Skewed Text Animation

Example Nine demonstrates the use of React Native Reanimated to create a skewed text animation. This component skews a text element along the x-axis using a timing animation. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create a shared value (skewX) which represents the skew angle of the animated text element. This value is essential for tracking and updating the element's skew during the animation.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared value. The style transforms the element by skewing it along the x-axis according to skewX.
  • Timing Animation: The withTiming function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.
  • Effect Hook: The useEffect hook is used to trigger the animation when the component mounts.

Component Structure

  • Shared Values Initialization:
    const skewX = useSharedValue(0);
    This line initializes the shared value skewX to 0.
  • Effect Hook: The useEffect hook triggers the animation when the component mounts.
    useEffect(() => {
      skewX.value = withTiming(20, { duration: 2000 });
    }, []);
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => ({
      transform: [{ skewX: `${skewX.value}deg` }],
    }));
    This hook creates an animated style that updates the element's transform property based on the current value of skewX.
  • Restart Animation: Function to restart the animation by resetting and reanimating the skewX value.
    const restartAnimation = () => {
      skewX.value = 0;
      skewX.value = withTiming(20, { duration: 2000 });
    };
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.1}
        title="Skewed Text"
        resetAnimation={restartAnimation}
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Animated.Text
            style={[
              animatedStyles,
              textShadows.glow200Sm,
              { fontFamily: "Play-Bold", fontSize: 33 },
            ]}
          >
            Skewed Text
          </Animated.Text>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated text element styled with both static and animated styles, representing text that skews along the x-axis.

Example Ten: Sequenced Skewed Text

Example Ten demonstrates the use of React Native Reanimated to create a sequenced skew animation. This component skews a text element back and forth in a sequence using timing animations. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create a shared value (skewX) which represents the skew angle of the animated text element. This value is essential for tracking and updating the element's skew during the animation.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared value. The style transforms the element by skewing it along the x-axis according to skewX.
  • Timing Animation: The withTiming function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.
  • Sequenced Animation: The withSequence function is used to create a sequence of animations that play one after the other.
  • Effect Hook: The useEffect hook is used to trigger the animation when the component mounts.

Component Structure

  • Shared Values Initialization:
    const skewX = useSharedValue(0);
    This line initializes the shared value skewX to 0.
  • Effect Hook: The useEffect hook triggers the animation sequence when the component mounts.
    useEffect(() => {
      skewX.value = withSequence(
        withTiming(20, { duration: 1000 }),
        withTiming(-20, { duration: 1000 }),
        withTiming(10, { duration: 1000 }),
        withTiming(-10, { duration: 1000 }),
        withTiming(0, { duration: 1000 })
      );
    }, []);
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => ({
      transform: [{ skewX: `${skewX.value}deg` }],
    }));
    This hook creates an animated style that updates the element's transform property based on the current value of skewX.
  • Restart Animation: Function to restart the animation by resetting and reanimating the skewX value.
    const restartAnimation = () => {
      skewX.value = 0;
      skewX.value = withSequence(
        withTiming(30, { duration: 1000 }),
        withTiming(-30, { duration: 1000 }),
        withTiming(20, { duration: 1000 }),
        withTiming(-20, { duration: 1000 }),
        withTiming(0, { duration: 1000 })
      );
    };
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.1}
        title="Sequenced Skewed Text"
        resetAnimation={restartAnimation}
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Animated.Text
            style={[
              animatedStyles,
              textShadows.glow200Sm,
              { fontFamily: "Play-Bold", fontSize: 33 },
            ]}
          >
            Skewed Text
          </Animated.Text>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated text element styled with both static and animated styles, representing text that skews back and forth in a sequence.

Example Eleven: Opacity & Scale Animation

Example Eleven demonstrates the use of React Native Reanimated to create an animation that combines opacity and scale transformations. This component smoothly fades in and scales up a text element using timing animations. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create shared values (opacity and scale) which represent the opacity and scale of the animated text element. These values are essential for tracking and updating the element's opacity and scale during the animation.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared values. The style sets the element's opacity and transforms it by scaling according to opacity and scale.
  • Timing Animation: The withTiming function is used to animate the shared values with a timing effect, providing smooth and controlled animations.
  • Effect Hook: The useEffect hook is used to trigger the animation when the component mounts.

Component Structure

  • Shared Values Initialization:
    const opacity = useSharedValue(0);
    const scale = useSharedValue(0.5);
    These lines initialize the shared values opacity to 0 and scale to 0.5.
  • Animation Function: The opacityScale function defines the timing animations for opacity and scale.
    const opacityScale = () => {
      opacity.value = withTiming(1, { duration: 2000 });
      scale.value = withTiming(1, { duration: 2000 });
    };
  • Effect Hook: The useEffect hook triggers the animation when the component mounts.
    useEffect(() => {
      opacityScale();
    }, []);
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => ({
      opacity: opacity.value,
      transform: [{ scale: scale.value }],
    }));
    This hook creates an animated style that updates the element's opacity and transform properties based on the current values of opacity and scale.
  • Restart Animation: Function to restart the animation by resetting and reanimating the opacity and scale values.
    const restartAnimation = () => {
      opacity.value = 0;
      scale.value = 0.5;
      opacityScale();
    };
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.1}
        title="Opacity & Scale"
        resetAnimation={restartAnimation}
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Animated.Text
            style={[
              animatedStyles,
              textShadows.glow200Sm,
              { fontFamily: "Play-Bold", fontSize: 33 },
            ]}
          >
            Opacity & Scale
          </Animated.Text>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated text element styled with both static and animated styles, representing text that smoothly fades in and scales up.

Example Twelve: Bouncing Text Animation

Example Twelve demonstrates the use of React Native Reanimated to create a bouncing text animation. This component makes a text element bounce using a spring animation. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create a shared value (translateY) which represents the y position of the animated text element. This value is essential for tracking and updating the element's position during the animation.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared value. The style transforms the element by translating it along the y-axis according to translateY.
  • Spring Animation: The withSpring function is used to animate the shared value with a spring effect, providing a smooth and natural bouncing animation.
  • Effect Hook: The useEffect hook is used to trigger the animation when the component mounts.

Component Structure

  • Shared Values Initialization:
    const translateY = useSharedValue(0);
    This line initializes the shared value translateY to 0.
  • Bouncing Animation Function: The bouncingAnimation function defines the spring animation for the y-axis translation.
    const bouncingAnimation = () => {
      translateY.value = withSpring(-screenHeight * 0.13, {
        damping: 5,
        stiffness: 150,
      });
    };
  • Effect Hook: The useEffect hook triggers the bouncing animation when the component mounts.
    useEffect(() => {
      bouncingAnimation();
    }, []);
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => ({
      transform: [{ translateY: translateY.value }],
    }));
    This hook creates an animated style that updates the element's transform property based on the current value of translateY.
  • Restart Animation: Function to restart the animation by resetting and reanimating the translateY value.
    const restartAnimation = () => {
      translateY.value = 0;
      bouncingAnimation();
    };
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.2}
        title="Bouncing Text"
        resetAnimation={restartAnimation}
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "flex-end",
          }}
        >
          <Animated.Text
            style={[
              animatedStyles,
              textShadows.glow200Sm,
              { fontFamily: "Play-Bold", fontSize: 33 },
            ]}
          >
            Bouncing Text
          </Animated.Text>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated text element styled with both static and animated styles, representing text that bounces using a spring animation.

Example Thirteen: Rotating Color Text

Example Thirteen demonstrates the use of React Native Reanimated to create an animation that combines rotation and color transformation. This component rotates a text element while continuously changing its color using timing, repeat, and sequence animations. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create shared values (rotate and color) which represent the rotation angle and color transition state of the animated text element. These values are essential for tracking and updating the element's rotation and color during the animation.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared values. The style sets the element's rotation and color according to rotate and color.
  • Timing, Repeat, and Sequence Animations: The withTiming function is used to animate the shared values with a timing effect, withRepeat is used to repeat the animation, and withSequence is used to create a sequence of animations that play one after the other.
  • Effect Hook: The useEffect hook is used to trigger the animation when the component mounts.
  • Interpolate Color: The interpolateColor function is used to interpolate the color values based on the shared value.

Component Structure

  • Shared Values Initialization:
    const rotate = useSharedValue(0);
    const color = useSharedValue(0);
    These lines initialize the shared values rotate and color to 0.
  • Animation Function: The rotatingColor function defines the rotation and color animations using a combination of timing, repeat, and sequence animations.
    const rotatingColor = () => {
      rotate.value = withRepeat(
        withSequence(
          withTiming(360, { duration: 2000 }),
          withTiming(0, { duration: 0 })
        ),
        -1,
        false
      );
      color.value = withRepeat(withTiming(1, { duration: 5000 }), -1, true);
    };
  • Effect Hook: The useEffect hook triggers the animation when the component mounts.
    useEffect(() => {
      rotatingColor();
    }, []);
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => {
      const textColor = interpolateColor(
        color.value,
        [0, 0.5, 1],
        [col[300], col[400], col[500]]
      );
      return {
        transform: [{ rotate: `${rotate.value}deg` }],
        color: textColor,
      };
    });
    This hook creates an animated style that updates the element's transform and color properties based on the current values of rotate and color.
  • Restart Animation: Function to restart the animation by resetting and reanimating the rotate and color values.
    const restartAnimation = () => {
      rotate.value = 0;
      color.value = 0;
      rotatingColor();
    };
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.3}
        title="Rotating Color Text"
        resetAnimation={restartAnimation}
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Animated.Text
            style={[
              animatedStyles,
              textShadows.glow200Sm,
              { fontFamily: "Play-Bold", fontSize: 33 },
            ]}
          >
            Rotating Color
          </Animated.Text>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated text element styled with both static and animated styles, representing text that rotates and changes color in a continuous loop.

Example Fourteen: Pulsating Text

Example Fourteen demonstrates the use of React Native Reanimated to create a pulsating text animation. This component scales a text element up and down continuously to create a pulsating effect using timing and repeat animations. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Shared Values: useSharedValue is used to create a shared value (scale) which represents the scale of the animated text element. This value is essential for tracking and updating the element's scale during the animation.
  • Animated Styles: useAnimatedStyle creates an animated style that updates based on the shared value. The style transforms the element by scaling it according to scale.
  • Timing and Repeat Animations: The withTiming function is used to animate the shared value with a timing effect, and withRepeat is used to repeat the animation indefinitely.
  • Effect Hook: The useEffect hook is used to trigger the animation when the component mounts.
  • Easing: The Easing.ease function is used to create a smooth easing effect for the timing animation.

Component Structure

  • Shared Values Initialization:
    const scale = useSharedValue(1);
    This line initializes the shared value scale to 1.
  • Animation Function: The pulsatingText function defines the scaling animation using a combination of timing and repeat animations with easing.
    const pulsatingText = () => {
      scale.value = withRepeat(
        withTiming(1.4, { duration: 1000, easing: Easing.ease }),
        -1,
        true
      );
    };
  • Effect Hook: The useEffect hook triggers the animation when the component mounts.
    useEffect(() => {
      pulsatingText();
    }, []);
  • Animated Styles Definition:
    const animatedStyles = useAnimatedStyle(() => ({
      transform: [{ scale: scale.value }],
    }));
    This hook creates an animated style that updates the element's transform property based on the current value of scale.
  • Restart Animation: Function to restart the animation by resetting and reanimating the scale value.
    const restartAnimation = () => {
      scale.value = 1;
      pulsatingText();
    };
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.1}
        title="Pulsating Text"
        resetAnimation={restartAnimation}
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Animated.Text
            style={[
              animatedStyles,
              textShadows.glow200Sm,
              { fontFamily: "Play-Bold", fontSize: 33 },
            ]}
          >
            Pulsating Text
          </Animated.Text>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated text element styled with both static and animated styles, representing text that scales up and down continuously to create a pulsating effect.

Keyframes Animations

Keyframe animations allow for more complex and predefined animation sequences. Reanimated’s keyframe API makes it easy to define animations that change multiple properties over time.

Key Concepts:

Defining Keyframes: Using keyframes to specify animation states and transitions.

Combining Keyframes with Styles: Applying keyframe animations to styles.

Chaining Animations: Creating smooth transitions between keyframes.

Example Fifteen: Entering Keyframes

Example Fifteen demonstrates the use of React Native Reanimated to create an animation using keyframes. This component animates a text element using entering keyframes that control its opacity and translation along the y-axis. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • State Management: The useState hook is used to manage the restart state and the entering keyframe. The restart state is used to re-trigger the keyframe animation, while the entering keyframe defines the animation sequence.
  • Keyframes: The Keyframe API from React Native Reanimated is used to define the entering animation sequence. The keyframe controls the opacity and translation of the text element along the y-axis.
  • Effect Hook: The useEffect hook is used to reset the restart state after the animation is triggered.

Component Structure

  • State Initialization:
    const [restart, setRestart] = useState(false);
    const [enteringKeyframe, setEnteringKeyframe] = useState(
      new Keyframe({
        0: {
          opacity: 0,
          transform: [{ translateY: -50 }],
        },
        100: {
          opacity: 1,
          transform: [{ translateY: 0 }],
        },
      })
    );
    These lines initialize the state variables restart and enteringKeyframe. The keyframe animation is defined with an initial opacity of 0 and a translation of -50 units along the y-axis, and it transitions to an opacity of 1 and a translation of 0 units.
  • Restart Animation Function: The restartAnimation function redefines the entering keyframe and toggles the restart state to re-trigger the animation.
    const restartAnimation = () => {
      setEnteringKeyframe(
        new Keyframe({
          0: {
            opacity: 0,
            transform: [{ translateY: -50 }],
          },
          100: {
            opacity: 1,
            transform: [{ translateY: 0 }],
          },
        })
      );
      setRestart((prev) => !prev);
    };
  • Effect Hook: The useEffect hook resets the restart state after the animation is triggered.
    useEffect(() => {
      if (restart) {
        setRestart(false);
      }
    }, [restart]);
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.1}
        title="Entering Keyframes"
        resetAnimation={restartAnimation}
        headingLight
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Animated.View
            key={restart.toString()}
            entering={enteringKeyframe}
            style={[elementStyleTwo, { paddingHorizontal: 10 }]}
          >
            <TextLg>Entering Keyframes</TextLg>
          </Animated.View>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated view styled with both static and animated styles, representing text that animates using entering keyframes.

Example Sixteen: Sequential Keyframes

Example Sixteen demonstrates the use of React Native Reanimated to create an animation using sequential keyframes. This component animates a text element through a sequence of keyframes that control its opacity, translation, scaling, and rotation. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • State Management: The useState hook is used to manage the restart state and the entering keyframe. The restart state is used to re-trigger the keyframe animation, while the entering keyframe defines the animation sequence.
  • Keyframes: The Keyframe API from React Native Reanimated is used to define the sequential animation sequence. The keyframe controls the opacity, translation, scaling, and rotation of the text element.
  • Effect Hook: The useEffect hook is used to reset the restart state after the animation is triggered.

Component Structure

  • State Initialization:
    const [restart, setRestart] = useState(false);
    
    const keyframeAnimation = new Keyframe({
      0: {
        opacity: 0,
        transform: [{ translateY: -50 }, { scale: 0.5 }, { rotate: "0deg" }],
      },
      25: {
        opacity: 0.5,
        transform: [{ translateY: -50 }, { scale: 0.75 }, { rotate: "90deg" }],
      },
      50: {
        opacity: 0.75,
        transform: [{ translateY: 0 }, { scale: 1 }, { rotate: "180deg" }],
      },
      75: {
        opacity: 1,
        transform: [{ translateY: 50 }, { scale: 1.25 }, { rotate: "270deg" }],
      },
      100: {
        opacity: 1,
        transform: [{ translateY: 0 }, { scale: 1 }, { rotate: "360deg" }],
      },
    }).duration(500);
    
    const [enteringKeyframe, setEnteringKeyframe] = useState(keyframeAnimation);
    These lines initialize the state variables restart and enteringKeyframe. The keyframe animation is defined with sequential steps controlling opacity, translation, scaling, and rotation.
  • Restart Animation Function: The restartAnimation function redefines the entering keyframe and toggles the restart state to re-trigger the animation.
    const restartAnimation = () => {
      setEnteringKeyframe(keyframeAnimation);
      setRestart((prev) => !prev);
    };
  • Effect Hook: The useEffect hook resets the restart state after the animation is triggered.
    useEffect(() => {
      if (restart) {
        setRestart(false);
      }
    }, [restart]);
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.3}
        title="Sequential Keyframes"
        resetAnimation={restartAnimation}
        headingLight
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Animated.View
            key={restart.toString()}
            entering={enteringKeyframe}
            style={[elementStyleTwo, { paddingHorizontal: 10 }]}
          >
            <TextLg>Sequential Keyframes</TextLg>
          </Animated.View>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated view styled with both static and animated styles, representing text that animates through a sequence of keyframes.

Example Seventeen: Advanced Keyframes Sequence

Example Seventeen demonstrates the use of React Native Reanimated to create an advanced animation sequence using keyframes. This component animates a text element through a series of keyframes that control its opacity, translation, scaling, rotation, and background color. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • State Management: The useState hook is used to manage the restart state. The restart state is used to re-trigger the keyframe animation.
  • Keyframes: The Keyframe API from React Native Reanimated is used to define the advanced animation sequence. The keyframe controls the opacity, translation, scaling, rotation, and background color of the text element.
  • Effect Hook: The useEffect hook is used to reset the restart state after the animation is triggered.

Component Structure

  • State Initialization:
    const [restart, setRestart] = useState(false);
    
    const keyframeAnimation = new Keyframe({
      0: {
        opacity: 0,
        transform: [{ translateY: -100 }, { scale: 0.5 }, { rotate: "0deg" }],
        backgroundColor: col[300],
      },
      20: {
        opacity: 0.5,
        transform: [{ translateY: -50 }, { scale: 0.75 }, { rotate: "90deg" }],
        backgroundColor: col[400],
      },
      40: {
        opacity: 1,
        transform: [{ translateY: 0 }, { scale: 1 }, { rotate: "180deg" }],
        backgroundColor: col[500],
      },
      60: {
        opacity: 0.75,
        transform: [{ translateY: 50 }, { scale: 1.25 }, { rotate: "270deg" }],
        backgroundColor: col[600],
      },
      80: {
        opacity: 0.5,
        transform: [{ translateY: 100 }, { scale: 1.5 }, { rotate: "360deg" }],
        backgroundColor: col[500],
      },
      100: {
        opacity: 1,
        transform: [{ translateY: 0 }, { scale: 1 }, { rotate: "0deg" }],
        backgroundColor: col[400],
      },
    }).duration(2000);
    These lines initialize the state variable restart and define the keyframe animation with advanced sequential steps controlling opacity, translation, scaling, rotation, and background color.
  • Restart Animation Function: The restartAnimation function toggles the restart state to re-trigger the animation.
    const restartAnimation = () => {
      setRestart((prev) => !prev);
    };
  • Effect Hook: The useEffect hook resets the restart state after the animation is triggered.
    useEffect(() => {
      if (restart) {
        setRestart(false);
      }
    }, [restart]);
  • Rendering the Component:
    return (
      <AnimationContainer
        height={screenHeight * 0.3}
        title="Advanced Sequence"
        resetAnimation={restartAnimation}
        headingLight
      >
        <FlexFull
          style={{
            height: "100%",
            justifyContent: "center",
            alignItems: "center",
          }}
        >
          <Animated.View
            key={restart.toString()}
            entering={keyframeAnimation}
            style={[
              boxShadows.xl,
              {
                borderRadius: 20,
                justifyContent: "center",
                alignItems: "center",
              },
            ]}
          >
            <View
              style={{
                paddingHorizontal: 10,
                justifyContent: "center",
                alignItems: "center",
              }}
            >
              <TextLg>Advanced Sequence</TextLg>
            </View>
          </Animated.View>
        </FlexFull>
      </AnimationContainer>
    );
    The component renders an animated view styled with both static and animated styles, representing text that animates through an advanced sequence of keyframes.

Scroll-Triggered Animations

Animating based on scroll position can create engaging and intuitive UIs. Reanimated provides tools to trigger animations based on the scroll position.

Key Concepts:

Scroll Position Tracking: Using shared values to track scroll position.

Animating Elements Based on Scroll: Applying animations as the user scrolls.

Smooth Transitions: Ensuring smooth and performant scroll animations.

Example Eighteen: ScrollTo Component

Our final example demonstrates the use of React Native Reanimated to create a scrollable list that can be programmatically scrolled to specific items. This component utilizes animated references and shared values to control the scroll position of an Animated.ScrollView. Here’s a detailed breakdown of its functionality and implementation.

Key Features

  • Animated References: useAnimatedRef is used to create a reference to the Animated.ScrollView. This reference is essential for controlling the scroll position programmatically.
  • Shared Values: useSharedValue is used to create a shared value (scroll) which represents the current scroll position. This value is essential for tracking and updating the scroll position during the animation.
  • Derived Values: useDerivedValue is used to derive the scroll position from the shared value and trigger the scrollTo function to update the scroll position of the Animated.ScrollView.
  • ScrollTo Function: The scrollTo function is used to programmatically scroll to a specific position in the Animated.ScrollView based on the shared value.

Component Structure

  • Animated References and Shared Values Initialization:
    const animatedRef = useAnimatedRef<Animated.ScrollView>();
    const scroll = useSharedValue<number>(0);
    These lines initialize the animated reference animatedRef and the shared value scroll.
  • Derived Value and ScrollTo Function:The useDerivedValue hook derives the scroll position from the shared value and triggers the scrollTo function to update the scroll position.
    useDerivedValue(() => {
      scrollTo(
        animatedRef,
        0,
        scroll.value * SCROLL_CONTAINER_HEIGHT - 100,
        true
      );
    });
  • Items Array: An array of 100 items is created to populate the scrollable list.
    const items = Array.from(Array(100).keys());
  • Rendering the Component:
    return (
      <GradientTen style={{ paddingTop: 70 }}>
        <VStackFull style={{ height: screenHeight * 0.9, gap: 10 }}>
          <NavButton increment={-1} scroll={scroll} />
          <CenterHorizontalFull style={{ height: SCROLL_CONTAINER_HEIGHT }}>
            <Animated.ScrollView ref={animatedRef}>
              <VStackFull style={{ gap: 25, paddingVertical: 10 }}>
                {items.map((_, i) => (
                  <CenterHorizontalFull key={i}>
                    <View
                      style={[
                        elementStyleTwo,
                        {
                          height: 70,
                          width: screenWidth * 0.75,
                          justifyContent: "center",
                          alignItems: "center",
                        },
                      ]}
                    >
                      <TextXl style={{ textAlign: "center" }}>Item: {i}</TextXl>
                    </View>
                  </CenterHorizontalFull>
                ))}
              </VStackFull>
            </Animated.ScrollView>
          </CenterHorizontalFull>
          <NavButton increment={1} scroll={scroll} />
        </VStackFull>
      </GradientTen>
    );
    The component renders a gradient background with a scrollable list of items. Navigation buttons are provided to scroll up and down through the list.
  • NavButton Component: A custom button component is used to navigate through the list by updating the shared scroll value.
    const NavButton = ({
      increment,
      scroll,
    }: {
      increment: number;
      scroll: SharedValue<number>;
    }) => (
      <CenterHorizontalFull>
        <MyButton
          icon={
            increment > 0 ? "caret-down-circle-outline" : "caret-up-circle-outline"
          }
          onPress={() => {
            scroll.value =
              scroll.value + increment > 0
                ? scroll.value + increment
                : 100 - 1 + increment;
    
            if (scroll.value >= 100 - 2) scroll.value = 0;
          }}
          text={`Page  ${increment > 0 ? "down" : "up"}`}
        />
      </CenterHorizontalFull>
    );

Wrapping up

We've delved deeply into the capabilities and nuances of React Native Reanimated, showcasing a variety of animation techniques and their practical applications. From simple movements along the X and Y axes to sophisticated gesture-based interactions and advanced keyframe sequences, we've explored how React Native Reanimated can transform the user experience with smooth, interactive animations.

Key Takeaways

  • Shared Values and Animated Styles: We've seen how shared values (useSharedValue) and animated styles (useAnimatedStyle) form the backbone of reanimated components, enabling dynamic and responsive animations.
  • Timing and Spring Animations: Using withTiming and withSpring, we've created animations that smoothly transition between states or simulate natural physical behaviors like bouncing.
  • Gestures Integration: By combining Reanimated with react-native-gesture-handler, we've crafted interactive components that respond to user gestures, enhancing the interactivity of our apps.
  • Keyframes for Complex Animations: Keyframes allow for creating intricate animation sequences, giving fine-grained control over how elements transition between states. We demonstrated this with examples of text elements that transform through opacity, scale, rotation, and background color changes.
  • Scroll Control: Leveraging scrollTo and animated references, we've learned how to create scrollable lists that can be programmatically controlled, offering a more guided and interactive scrolling experience.
  • Text Animations: Various text animations showcased how to animate text properties like color, scale, rotation, and position, providing visually engaging effects that can be used to enhance UI elements.
  • Reanimated’s Flexibility: The examples demonstrate Reanimated’s flexibility and power in creating animations that range from simple transitions to complex sequences, making it an invaluable tool for React Native developers looking to add flair and interactivity to their applications.

Practical Application

Through these examples, you should now have a solid foundation to start implementing your own animations in React Native. The versatility of Reanimated opens up numerous possibilities for creating engaging, dynamic user interfaces. Whether you are building a simple app or a complex interactive experience, understanding and utilizing the techniques covered in this post will help you deliver a more polished and professional product.

Final Thoughts

Animation is a critical aspect of modern mobile app development, enhancing the user experience by making interactions more intuitive and visually appealing. React Native Reanimated stands out as a powerful library that not only makes it easier to implement these animations but also offers the performance and control needed to create sophisticated, fluid animations. By integrating these techniques into your projects, you can elevate the user experience and create applications that truly stand out.

Thank you for following along with this exploration of React Native Reanimated. I hope these insights and examples inspire you to experiment and create your own stunning animations. Keep pushing the boundaries of what’s possible, and happy animating!

© 2024 DarkViolet.ai All Rights Reserved