Working with Animations
1. Using Animated API
| Property | Description | Values |
|---|---|---|
| Animated.View | Component that can be animated | View component with animation support |
| Animated.Text | Text component with animation support | Text component with animation support |
| Animated.Image | Image component with animation support | Image component with animation support |
| Animated.ScrollView | ScrollView component with animation support | ScrollView component with animation support |
Example: Basic Animation
import React, { useRef } from 'react';
import { Animated, View } from 'react-native';
const BasicAnimation = () => {
const fadeAnim = useRef(new Animated.Value(0)).current;
React.useEffect(() => {
Animated.timing(fadeAnim, {
toValue: 1,
duration: 1000,
useNativeDriver: true
}).start();
}, []);
return (
<Animated.View style={{ opacity: fadeAnim }}>
<Text>Fade In</Text>
</Animated.View>
);
};
export default BasicAnimation;
Example: Rotation Animation
import React, { useRef } from 'react';
import { Animated, View } from 'react-native';
const RotationAnimation = () => {
const rotateAnim = useRef(new Animated.Value(0)).current;
React.useEffect(() => {
Animated.loop(
Animated.timing(rotateAnim, {
toValue: 360,
duration: 2000,
useNativeDriver: true
})
).start();
}, []);
return (
<Animated.View style={{
transform: [{ rotate: rotateAnim.interpolate({
inputRange: [0, 360],
outputRange: ['0deg', '360deg']
}) }]
}}>
<Text>Rotating</Text>
</Animated.View>
);
};
export default RotationAnimation;
Note: Use
useNativeDriver: true for better performance.
Warning: Ensure all animated values are initialized with
new Animated.Value().
2. Creating Timing Animations
| Property | Description | Values |
|---|---|---|
| duration | Duration of the animation in milliseconds | number |
| easing | Easing function to control animation curve | 'linear' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'cubic-bezier(n,n,n,n)' |
| delay | Delay before animation starts in milliseconds | number |
| repeat | Number of times to repeat the animation | number | 'infinite' |
| repeatType | How to repeat the animation | 'reverse' | 'reset' |
Example: Basic timing animation
import Animated, { FadeIn } from 'react-native-animatable';
<Animated.View
animation={FadeIn}
duration={1000}
easing="ease-in-out"
delay={200}
>
<Text>Animated Text</Text>
</Animated.View>
Example: Custom easing function
import Animated from 'react-native-reanimated';
const customEasing = Animated.Easing.bezier(0.25, 0.1, 0.25, 1);
<Animated.View
style={[
styles.box,
{
animation: Animated.timing(styles.box, {
toValue: 100,
duration: 500,
easing: customEasing,
}).start(),
},
]}
></Animated.View>
3. Using Spring Animations
| Property | Description | Default | Notes |
|---|---|---|---|
| mass | Mass of the object being animated | 1 |
Higher mass results in slower response to forces |
| stiffness | Stiffness of the spring | 100 |
Higher stiffness makes the animation more rigid |
| damping | Damping factor of the spring | 10 |
Higher damping reduces oscillation |
| restDisplacementThreshold | Threshold for displacement to consider as at rest | 0.001 |
Used to optimize performance by stopping animation when displacement is negligible |
| restSpeedThreshold | Threshold for speed to consider as at rest | 0.001 |
Used to optimize performance by stopping animation when speed is negligible |
Example: Basic Spring Animation
import Animated, { useAnimatedStyle, withSpring } from 'react-native-reanimated';
const SpringExample = () => {
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateX: withSpring(100),
},
],
};
});
return <Animated.View style={animatedStyle} />;
};
Example: Spring with Custom Configuration
import Animated, { useAnimatedStyle, withSpring } from 'react-native-reanimated';
const CustomSpringExample = () => {
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [
{
translateY: withSpring(200, {
stiffness: 150,
damping: 20,
mass: 1.5,
}),
},
],
};
});
return <Animated.View style={animatedStyle} />;
};
Note: The spring animation uses a physics-based model to simulate real-world spring behavior. It is ideal for creating natural, organic motion in UI elements.
4. Creating Sequences
Example: Basic Sequence
import { Animated } from 'react-native';
const fadeAnim = new Animated.Value(0);
const scaleAnim = new Animated.Value(1);
Animated.sequence([
Animated.timing(fadeAnim, {
toValue: 1,
duration: 500,
useNativeDriver: true,
}),
Animated.timing(scaleAnim, {
toValue: 1.5,
duration: 300,
useNativeDriver: true,
}),
]).start();
| Property | Description | Values |
|---|---|---|
| Animated.sequence | Creates a sequence of animations to run in order | Array<Animated.Animation> |
| duration | Duration of each animation in milliseconds | number |
| useNativeDriver | Enables native driver for performance | true or false |
Note: Sequences run animations one after another in the order specified.
Warning: All animations in a sequence must use the same
useNativeDriver setting.
5. Running Parallel Animations
Parallel animations in Expo use the Animated.parallel function to run multiple animations simultaneously. This is useful for creating complex animation sequences that involve several properties changing at once.
| Property | Description | Values |
|---|---|---|
| animations | An array of animation objects to run in parallel | Array of Animated instances |
Example: Running Parallel Animations
import React, { useRef } from 'react';
import { Animated, View } from 'react-native';
const ParallelAnimationExample = () => {
const fadeAnim = useRef(new Animated.Value(0)).current;
const scaleAnim = useRef(new Animated.Value(1)).current;
const startParallelAnimation = () => {
Animated.parallel([
Animated.timing(fadeAnim, {
toValue: 1,
duration: 1000,
useNativeDriver: true,
}),
Animated.timing(scaleAnim, {
toValue: 1.5,
duration: 1000,
useNativeDriver: true,
}),
]).start();
};
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Animated.View
style={{
width: 100,
height: 100,
backgroundColor: 'blue',
opacity: fadeAnim,
transform: [{ scale: scaleAnim }],
}}
>
</Animated.View>
<View style={{ marginTop: 20 }}>
<Animated.Text
style={{
fontSize: 20,
opacity: fadeAnim,
}}
>
Animated Text
</Animated.Text>
</View>
</View>
);
};
export default ParallelAnimationExample;
6. Using Stagger Animations
Stagger animations in Expo allow you to create sequential animations with a time delay between each element, enhancing visual flow and engagement.
| Property | Description | Default Value | Notes |
|---|---|---|---|
| stagger | Applies a stagger delay to each animation in a group | false |
Can be a number (in ms) or an object with delay and duration |
| delay | Initial delay before the first animation starts | 0 |
Used in conjunction with stagger |
Example: Staggering Animations
import React from 'react';
import { View, Text } from 'react-native';
import { Animated } from 'react-native';
const StaggerExample = () => {
const animations = [0, 1, 2, 3].map(i => new Animated.Value(0));
const startStagger = () => {
animations.forEach((anim, index) => {
Animated.timing(anim, {
toValue: 1,
duration: 500,
delay: index * 200, // Stagger by 200ms
useNativeDriver: true,
}).start();
});
};
return (
<View style={{ flexDirection: 'row', justifyContent: 'space-around' }}>
{animations.map((anim, index) => (
<Animated.View
key={index}
style={{
width: 50,
height: 50,
backgroundColor: 'blue',
opacity: anim,
transform: [{ scale: anim }],
}}
/>
))}
</View>
);
};
export default StaggerExample;
Note: The
stagger property is not a built-in in React Native's Animated API, but can be implemented using delay in individual animations.
Warning: Ensure that the
useNativeDriver is set to true for performance benefits when using Animated.7. Implementing Native Driver
| Property | Description | Values | Notes |
|---|---|---|---|
| useNativeDriver | Flag to enable native driver for animations | true / false |
Must be set to true for animations to use native driver. Only works with specific animated properties. |
Example: Using Native Driver
import Animated, { useAnimatedStyle, useSharedValue } from 'react-native-animated';
const AnimatedComponent = () => {
const opacity = useSharedValue(1);
const animatedStyle = useAnimatedStyle(() => {
return {
opacity: opacity.value,
};
});
const startAnimation = () => {
Animated.timing(opacity, {
toValue: 0,
duration: 1000,
useNativeDriver: true, // Enable native driver
}).start();
};
return <Animated.View style={animatedStyle} />;
};
Note: Native driver is only supported for a limited set of animated properties. It provides better performance by running animations on the native thread instead of JavaScript.
Warning: Setting
useNativeDriver to true will cause the animation to not work if any animated property is not supported by the native driver.
8. Using Reanimated
Example: Basic Reanimated Animation
import { View, Button } from 'react-native';
import { useSharedValue, withTiming } from 'react-native-reanimated';
export default function AnimatedComponent() {
const opacity = useSharedValue(1);
const animate = () => {
opacity.value = withTiming(opacity.value === 1 ? 0 : 1, { duration: 500 });
};
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<View style={{
width: 100,
height: 100,
backgroundColor: 'blue',
opacity: opacity.value
}} />
<Button title="Animate" onPress={animate} />
</View>
);
}
| Property | Description | Values | Notes |
|---|---|---|---|
| useSharedValue | Creates a shared value that can be animated | initialValue |
Used for animating values in Reanimated |
| withTiming | Applies a timing animation to a value | value, config |
Config includes duration and easing |
| withSpring | Applies a spring animation to a value | value, config |
Config includes stiffness, damping, mass |
Note: Reanimated requires native code integration and must be installed via Expo.
Warning: Reanimated animations run on the native thread and cannot use React state directly.
Key Features of Reanimated
- High-performance animations using native thread
- Supports complex animations like springs and timing
- Can be used with gesture handlers for interactive animations
- Requires Expo to work in managed workflow
9. Creating Shared Values
Shared values in Expo animations allow multiple animated properties to be linked together, enabling complex animation behaviors where one property's value influences another.
| Property | Description | Usage |
|---|---|---|
| sharedValue | Represents a value that can be shared across multiple animated properties. | const sharedValue = useSharedValue(0); |
| value | Gets or sets the current value of the shared value. | sharedValue.value = 100; |
Example: Using Shared Values in Animations
import { useSharedValue, withTiming } from 'react-native-reanimated';
const sharedValue = useSharedValue(0);
const animate = () => {
sharedValue.value = withTiming(100, { duration: 500 });
};
// In a component:
<Animated.View
style={{
transform: [{ translateX: sharedValue }],
}}
></Animated.View>
Note: Shared values must be initialized with a starting value and can only be updated using animation functions like
withTiming, withSpring, or withDecay.
10. Using Animated Styles
| Property | Values | Description |
|---|---|---|
| animatedStyle | Animated.StyleSheet |
Applies animated styles to components using Animated.View. |
| useNativeDriver | true | false |
Enables hardware acceleration for animations. Defaults to false. |
| duration | number |
Duration of the animation in milliseconds. |
Example: Basic Animated Style
import React, { useRef } from 'react';
import { Animated, View } from 'react-native';
const AnimatedStyleExample = () => {
const fadeAnim = useRef(new Animated.Value(0)).current;
Animated.timing(fadeAnim, {
toValue: 1,
duration: 500,
useNativeDriver: true
}).start();
return (
<Animated.View
style={{
opacity: fadeAnim,
width: 100,
height: 100,
backgroundColor: 'blue'
}}
>
</Animated.View>
);
};
export default AnimatedStyleExample;
Note:
useNativeDriver must be set to true for performance on iOS and Android.
Warning: Not all style properties support
useNativeDriver. Properties like transform and opacity are supported.
11. Implementing Gesture Handler Integration
Example: Basic Pan Gesture
import { PanGestureHandler } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const panGesture = Gesture.Pan()
.onUpdate((event) => {
translateX.value = event.translationX;
translateY.value = event.translationY;
})
.onEnd(() => {
translateX.value = 0;
translateY.value = 0;
});
const animatedStyle = useAnimatedStyle(() => ({
transform: [
{ translateX: translateX.value },
{ translateY: translateY.value }
]
}));
<PanGestureHandler onGestureEvent={panGesture}>
<Animated.View style={animatedStyle}>
<View style={{ width: 100, height: 100, backgroundColor: 'blue' }} />
</Animated.View>
</PanGestureHandler>
| Property | Description | Values | Notes |
|---|---|---|---|
| onGestureEvent | Callback for gesture events | function |
Required for handling gesture updates |
| onHandlerStateChange | Callback for handler state changes | function |
Use to detect gesture start/end |
Note: Ensure
react-native-gesture-handler is properly installed and linked for iOS and Android.
Warning:
useAnimatedStyle must be used inside a component that is wrapped in Animated.View or similar.
Integration Steps
- Install
react-native-gesture-handler - Link the library for iOS and Android
- Create shared values for animated properties
- Define gesture using
Gesture.Pan() - Attach gesture to component with
PanGestureHandler
12. Creating Layout Animations
| Property | Description | Values | Notes |
|---|---|---|---|
| layoutAnimation | Enables layout animations for components | true, false |
Must be set on the root component or parent container |
| duration | Duration of the layout animation in milliseconds | number |
Default is 200ms |
| easing | Easing function for the animation | 'easeIn', 'easeOut', 'easeInOut' |
Can be customized using Easing from React Native |
Example: Enabling Layout Animation
import { LayoutAnimation } from 'react-native';<br><br>const toggleLayout = () => {<br> LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);<br>};
Note: Layout animations work best with components that change size or position, such as
View, Text, and Image.
Warning: Layout animations may not work as expected in all cases, especially with complex nested components or custom views.