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
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.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
.withSpring
function is used to animate the shared values with a spring effect, providing a smooth and natural animation.Component Structure
const offsetX = useSharedValue(0);
const offsetY = useSharedValue(0);
These lines initialize the shared values offsetX
and offsetY
to zero.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
.const getRandomSign = () => {
return Math.random() < 0.5 ? -1 : 1;
};
const resetAnimation = () => {
offsetX.value = withSpring(0);
offsetY.value = withSpring(0);
};
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
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.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
.withTiming
function is used to animate the shared value with a timed effect, providing a smooth and controlled animation.Component Structure
const offset = useSharedValue(-150);
This line initializes the shared value offset
to -150.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
.const resetAnimation = () => {
offset.value = -150;
};
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
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.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
API from react-native-gesture-handler
is used to handle pan gestures, allowing the element to be dragged around the screen.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
const offsetX = useSharedValue(0);
const offsetY = useSharedValue(0);
const startX = useSharedValue(0);
const startY = useSharedValue(0);
These lines initialize the shared values to zero.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.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);
});
offsetX
and offsetY
values based on the gesture's translation.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
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.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
API from react-native-gesture-handler
is used to handle pan gestures, allowing the element to be dragged around the screen.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
const offsetX = useSharedValue(0);
const offsetY = useSharedValue(0);
const startX = useSharedValue(0);
const startY = useSharedValue(0);
These lines initialize the shared values to zero.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.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,
});
});
offsetX
and offsetY
values based on the gesture's translation.const resetAnimation = () => {
offsetX.value = 0;
offsetY.value = 0;
};
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
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.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
API from react-native-gesture-handler
is used to handle pan and pinch gestures, allowing the element to be dragged and scaled.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
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.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.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);
offsetX
and offsetY
values based on the gesture's translation.scale
value based on the gesture's scale.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
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.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
.withTiming
function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const translateX = useSharedValue(-350);
This line initializes the shared value translateX
to -350, starting the text element off-screen to the left.useEffect
hook triggers the animation when the component mounts.useEffect(() => {
translateX.value = withTiming(0, { duration: 2000 });
}, []);
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
.translateX
value.const restartAnimation = () => {
translateX.value = -350;
translateX.value = withTiming(0, { duration: 2000 });
};
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
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.useAnimatedStyle
creates an animated style that updates based on the shared value. The style interpolates the color based on the value of color
.withTiming
function is used to animate the shared value with a timing effect, and withRepeat
is used to repeat the animation indefinitely.useEffect
hook is used to trigger the animation when the component mounts.interpolateColor
function is used to interpolate the color values based on the shared value.Component Structure
const color = useSharedValue(0);
This line initializes the shared value color
to 0.useEffect
hook triggers the color-shifting animation when the component mounts.useEffect(() => {
color.value = withRepeat(withTiming(1, { duration: 7000 }), -1, true);
}, []);
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
.color
value.const restartAnimation = () => {
cancelAnimation(color);
color.value = 0;
color.value = withRepeat(withTiming(1, { duration: 7000 }), -1, true);
};
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
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.useAnimatedStyle
creates an animated style that updates based on the shared value. The style transforms the element by rotating it according to rotation
.withTiming
function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const rotation = useSharedValue(0);
This line initializes the shared value rotation
to 0.useEffect
hook triggers the animation when the component mounts.useEffect(() => {
rotation.value = withTiming(360, { duration: 2000 });
}, []);
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
.rotation
value.const restartAnimation = () => {
rotation.value = 0;
rotation.value = withTiming(360, { duration: 2000 });
};
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
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.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
.withTiming
function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const skewX = useSharedValue(0);
This line initializes the shared value skewX
to 0.useEffect
hook triggers the animation when the component mounts.useEffect(() => {
skewX.value = withTiming(20, { duration: 2000 });
}, []);
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
.skewX
value.const restartAnimation = () => {
skewX.value = 0;
skewX.value = withTiming(20, { duration: 2000 });
};
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
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.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
.withTiming
function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.withSequence
function is used to create a sequence of animations that play one after the other.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const skewX = useSharedValue(0);
This line initializes the shared value skewX
to 0.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 })
);
}, []);
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
.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 })
);
};
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
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.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
.withTiming
function is used to animate the shared values with a timing effect, providing smooth and controlled animations.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const opacity = useSharedValue(0);
const scale = useSharedValue(0.5);
These lines initialize the shared values opacity
to 0 and scale
to 0.5.opacityScale
function defines the timing animations for opacity and scale.const opacityScale = () => {
opacity.value = withTiming(1, { duration: 2000 });
scale.value = withTiming(1, { duration: 2000 });
};
useEffect
hook triggers the animation when the component mounts.useEffect(() => {
opacityScale();
}, []);
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
.opacity
and scale
values.const restartAnimation = () => {
opacity.value = 0;
scale.value = 0.5;
opacityScale();
};
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
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.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
.withSpring
function is used to animate the shared value with a spring effect, providing a smooth and natural bouncing animation.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const translateY = useSharedValue(0);
This line initializes the shared value translateY
to 0.bouncingAnimation
function defines the spring animation for the y-axis translation.const bouncingAnimation = () => {
translateY.value = withSpring(-screenHeight * 0.13, {
damping: 5,
stiffness: 150,
});
};
useEffect
hook triggers the bouncing animation when the component mounts.useEffect(() => {
bouncingAnimation();
}, []);
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
.translateY
value.const restartAnimation = () => {
translateY.value = 0;
bouncingAnimation();
};
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
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.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
.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.useEffect
hook is used to trigger the animation when the component mounts.interpolateColor
function is used to interpolate the color values based on the shared value.Component Structure
const rotate = useSharedValue(0);
const color = useSharedValue(0);
These lines initialize the shared values rotate
and color
to 0.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);
};
useEffect
hook triggers the animation when the component mounts.useEffect(() => {
rotatingColor();
}, []);
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
.rotate
and color
values.const restartAnimation = () => {
rotate.value = 0;
color.value = 0;
rotatingColor();
};
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
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.useAnimatedStyle
creates an animated style that updates based on the shared value. The style transforms the element by scaling it according to scale
.withTiming
function is used to animate the shared value with a timing effect, and withRepeat
is used to repeat the animation indefinitely.useEffect
hook is used to trigger the animation when the component mounts.Easing.ease
function is used to create a smooth easing effect for the timing animation.Component Structure
const scale = useSharedValue(1);
This line initializes the shared value scale
to 1.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
);
};
useEffect
hook triggers the animation when the component mounts.useEffect(() => {
pulsatingText();
}, []);
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
.scale
value.const restartAnimation = () => {
scale.value = 1;
pulsatingText();
};
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
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.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.useEffect
hook is used to reset the restart state after the animation is triggered.Component Structure
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.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);
};
useEffect
hook resets the restart state after the animation is triggered.useEffect(() => {
if (restart) {
setRestart(false);
}
}, [restart]);
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
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.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.useEffect
hook is used to reset the restart state after the animation is triggered.Component Structure
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.restartAnimation
function redefines the entering keyframe and toggles the restart state to re-trigger the animation.const restartAnimation = () => {
setEnteringKeyframe(keyframeAnimation);
setRestart((prev) => !prev);
};
useEffect
hook resets the restart state after the animation is triggered.useEffect(() => {
if (restart) {
setRestart(false);
}
}, [restart]);
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
useState
hook is used to manage the restart state. The restart state is used to re-trigger the keyframe animation.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.useEffect
hook is used to reset the restart state after the animation is triggered.Component Structure
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.restartAnimation
function toggles the restart state to re-trigger the animation.const restartAnimation = () => {
setRestart((prev) => !prev);
};
useEffect
hook resets the restart state after the animation is triggered.useEffect(() => {
if (restart) {
setRestart(false);
}
}, [restart]);
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
useAnimatedRef
is used to create a reference to the Animated.ScrollView
. This reference is essential for controlling the scroll position programmatically.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.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 is used to programmatically scroll to a specific position in the Animated.ScrollView
based on the shared value.Component Structure
const animatedRef = useAnimatedRef<Animated.ScrollView>();
const scroll = useSharedValue<number>(0);
These lines initialize the animated reference animatedRef
and the shared value scroll
.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
);
});
const items = Array.from(Array(100).keys());
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.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
useSharedValue
) and animated styles (useAnimatedStyle
) form the backbone of reanimated components, enabling dynamic and responsive animations.withTiming
and withSpring
, we've created animations that smoothly transition between states or simulate natural physical behaviors like bouncing.react-native-gesture-handler
, we've crafted interactive components that respond to user gestures, enhancing the interactivity of our apps.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.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!
Evan Marie Carr
June 05, 2024
App Design
Mobile Apps
React Native
Expo
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
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
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.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
.withSpring
function is used to animate the shared values with a spring effect, providing a smooth and natural animation.Component Structure
const offsetX = useSharedValue(0);
const offsetY = useSharedValue(0);
These lines initialize the shared values offsetX
and offsetY
to zero.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
.const getRandomSign = () => {
return Math.random() < 0.5 ? -1 : 1;
};
const resetAnimation = () => {
offsetX.value = withSpring(0);
offsetY.value = withSpring(0);
};
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
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.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
.withTiming
function is used to animate the shared value with a timed effect, providing a smooth and controlled animation.Component Structure
const offset = useSharedValue(-150);
This line initializes the shared value offset
to -150.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
.const resetAnimation = () => {
offset.value = -150;
};
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
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.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
API from react-native-gesture-handler
is used to handle pan gestures, allowing the element to be dragged around the screen.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
const offsetX = useSharedValue(0);
const offsetY = useSharedValue(0);
const startX = useSharedValue(0);
const startY = useSharedValue(0);
These lines initialize the shared values to zero.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.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);
});
offsetX
and offsetY
values based on the gesture's translation.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
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.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
API from react-native-gesture-handler
is used to handle pan gestures, allowing the element to be dragged around the screen.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
const offsetX = useSharedValue(0);
const offsetY = useSharedValue(0);
const startX = useSharedValue(0);
const startY = useSharedValue(0);
These lines initialize the shared values to zero.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.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,
});
});
offsetX
and offsetY
values based on the gesture's translation.const resetAnimation = () => {
offsetX.value = 0;
offsetY.value = 0;
};
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
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.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
API from react-native-gesture-handler
is used to handle pan and pinch gestures, allowing the element to be dragged and scaled.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
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.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.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);
offsetX
and offsetY
values based on the gesture's translation.scale
value based on the gesture's scale.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
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.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
.withTiming
function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const translateX = useSharedValue(-350);
This line initializes the shared value translateX
to -350, starting the text element off-screen to the left.useEffect
hook triggers the animation when the component mounts.useEffect(() => {
translateX.value = withTiming(0, { duration: 2000 });
}, []);
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
.translateX
value.const restartAnimation = () => {
translateX.value = -350;
translateX.value = withTiming(0, { duration: 2000 });
};
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
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.useAnimatedStyle
creates an animated style that updates based on the shared value. The style interpolates the color based on the value of color
.withTiming
function is used to animate the shared value with a timing effect, and withRepeat
is used to repeat the animation indefinitely.useEffect
hook is used to trigger the animation when the component mounts.interpolateColor
function is used to interpolate the color values based on the shared value.Component Structure
const color = useSharedValue(0);
This line initializes the shared value color
to 0.useEffect
hook triggers the color-shifting animation when the component mounts.useEffect(() => {
color.value = withRepeat(withTiming(1, { duration: 7000 }), -1, true);
}, []);
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
.color
value.const restartAnimation = () => {
cancelAnimation(color);
color.value = 0;
color.value = withRepeat(withTiming(1, { duration: 7000 }), -1, true);
};
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
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.useAnimatedStyle
creates an animated style that updates based on the shared value. The style transforms the element by rotating it according to rotation
.withTiming
function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const rotation = useSharedValue(0);
This line initializes the shared value rotation
to 0.useEffect
hook triggers the animation when the component mounts.useEffect(() => {
rotation.value = withTiming(360, { duration: 2000 });
}, []);
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
.rotation
value.const restartAnimation = () => {
rotation.value = 0;
rotation.value = withTiming(360, { duration: 2000 });
};
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
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.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
.withTiming
function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const skewX = useSharedValue(0);
This line initializes the shared value skewX
to 0.useEffect
hook triggers the animation when the component mounts.useEffect(() => {
skewX.value = withTiming(20, { duration: 2000 });
}, []);
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
.skewX
value.const restartAnimation = () => {
skewX.value = 0;
skewX.value = withTiming(20, { duration: 2000 });
};
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
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.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
.withTiming
function is used to animate the shared value with a timing effect, providing a smooth and controlled animation.withSequence
function is used to create a sequence of animations that play one after the other.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const skewX = useSharedValue(0);
This line initializes the shared value skewX
to 0.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 })
);
}, []);
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
.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 })
);
};
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
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.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
.withTiming
function is used to animate the shared values with a timing effect, providing smooth and controlled animations.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const opacity = useSharedValue(0);
const scale = useSharedValue(0.5);
These lines initialize the shared values opacity
to 0 and scale
to 0.5.opacityScale
function defines the timing animations for opacity and scale.const opacityScale = () => {
opacity.value = withTiming(1, { duration: 2000 });
scale.value = withTiming(1, { duration: 2000 });
};
useEffect
hook triggers the animation when the component mounts.useEffect(() => {
opacityScale();
}, []);
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
.opacity
and scale
values.const restartAnimation = () => {
opacity.value = 0;
scale.value = 0.5;
opacityScale();
};
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
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.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
.withSpring
function is used to animate the shared value with a spring effect, providing a smooth and natural bouncing animation.useEffect
hook is used to trigger the animation when the component mounts.Component Structure
const translateY = useSharedValue(0);
This line initializes the shared value translateY
to 0.bouncingAnimation
function defines the spring animation for the y-axis translation.const bouncingAnimation = () => {
translateY.value = withSpring(-screenHeight * 0.13, {
damping: 5,
stiffness: 150,
});
};
useEffect
hook triggers the bouncing animation when the component mounts.useEffect(() => {
bouncingAnimation();
}, []);
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
.translateY
value.const restartAnimation = () => {
translateY.value = 0;
bouncingAnimation();
};
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
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.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
.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.useEffect
hook is used to trigger the animation when the component mounts.interpolateColor
function is used to interpolate the color values based on the shared value.Component Structure
const rotate = useSharedValue(0);
const color = useSharedValue(0);
These lines initialize the shared values rotate
and color
to 0.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);
};
useEffect
hook triggers the animation when the component mounts.useEffect(() => {
rotatingColor();
}, []);
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
.rotate
and color
values.const restartAnimation = () => {
rotate.value = 0;
color.value = 0;
rotatingColor();
};
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
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.useAnimatedStyle
creates an animated style that updates based on the shared value. The style transforms the element by scaling it according to scale
.withTiming
function is used to animate the shared value with a timing effect, and withRepeat
is used to repeat the animation indefinitely.useEffect
hook is used to trigger the animation when the component mounts.Easing.ease
function is used to create a smooth easing effect for the timing animation.Component Structure
const scale = useSharedValue(1);
This line initializes the shared value scale
to 1.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
);
};
useEffect
hook triggers the animation when the component mounts.useEffect(() => {
pulsatingText();
}, []);
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
.scale
value.const restartAnimation = () => {
scale.value = 1;
pulsatingText();
};
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
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.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.useEffect
hook is used to reset the restart state after the animation is triggered.Component Structure
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.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);
};
useEffect
hook resets the restart state after the animation is triggered.useEffect(() => {
if (restart) {
setRestart(false);
}
}, [restart]);
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
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.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.useEffect
hook is used to reset the restart state after the animation is triggered.Component Structure
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.restartAnimation
function redefines the entering keyframe and toggles the restart state to re-trigger the animation.const restartAnimation = () => {
setEnteringKeyframe(keyframeAnimation);
setRestart((prev) => !prev);
};
useEffect
hook resets the restart state after the animation is triggered.useEffect(() => {
if (restart) {
setRestart(false);
}
}, [restart]);
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
useState
hook is used to manage the restart state. The restart state is used to re-trigger the keyframe animation.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.useEffect
hook is used to reset the restart state after the animation is triggered.Component Structure
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.restartAnimation
function toggles the restart state to re-trigger the animation.const restartAnimation = () => {
setRestart((prev) => !prev);
};
useEffect
hook resets the restart state after the animation is triggered.useEffect(() => {
if (restart) {
setRestart(false);
}
}, [restart]);
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
useAnimatedRef
is used to create a reference to the Animated.ScrollView
. This reference is essential for controlling the scroll position programmatically.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.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 is used to programmatically scroll to a specific position in the Animated.ScrollView
based on the shared value.Component Structure
const animatedRef = useAnimatedRef<Animated.ScrollView>();
const scroll = useSharedValue<number>(0);
These lines initialize the animated reference animatedRef
and the shared value scroll
.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
);
});
const items = Array.from(Array(100).keys());
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.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
useSharedValue
) and animated styles (useAnimatedStyle
) form the backbone of reanimated components, enabling dynamic and responsive animations.withTiming
and withSpring
, we've created animations that smoothly transition between states or simulate natural physical behaviors like bouncing.react-native-gesture-handler
, we've crafted interactive components that respond to user gestures, enhancing the interactivity of our apps.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.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