Working with Advanced Animations
1. Using Worklets
Example: Basic Worklet Usage
import { runOnJS } from 'react-native-reanimated';
function useWorklet() {
const animatedValue = useSharedValue(0);
const workletFunction = Worklets.createRunInContext(() => {
'worklet';
animatedValue.value = 100;
});
runOnJS(workletFunction)();
}
export default useWorklet;
| Property | Description | Notes |
|---|---|---|
| Worklets.createRunInContext | Creates a worklet function that runs in the UI thread | Must be called with a function body wrapped in quotes |
| runOnJS | Runs a function on the JavaScript thread | Useful for updating state or calling JS-only functions |
2. Creating Animated Reactions
Example: Basic Animated Reaction
import React from 'react';
import { Animated, TouchableOpacity } from 'react-native';
const AnimatedReaction = () => {
const scale = new Animated.Value(1);
const handlePress = () => {
Animated.sequence([
Animated.timing(scale, {
toValue: 1.2,
duration: 100,
useNativeDriver: true,
}),
Animated.timing(scale, {
toValue: 1,
duration: 100,
useNativeDriver: true,
}),
]).start();
};
return (
<TouchableOpacity onPress={handlePress}>
<Animated.View
style={{
transform: [{ scale }],
}}
>
<View style={{ width: 50, height: 50, backgroundColor: 'blue' }} />
</Animated.View>
</TouchableOpacity>
);
};
export default AnimatedReaction;
| Property | Description | Values |
|---|---|---|
| Animated.sequence | Runs animations in sequence | Array<Animated.Animation> |
| Animated.timing | Animates a value over time | { toValue: number, duration: number } |
| useNativeDriver | Enables hardware acceleration | true or false |
Note: Always set
useNativeDriver to true for better performance.
Warning: Ensure all animated values are initialized with
new Animated.Value().
3. Interpolating Values
| Property | Description | Values | Notes |
|---|---|---|---|
| inputRange | Array of input values that map to the output range | [0, 1] |
Must be in ascending order |
| outputRange | Array of output values that map to the input range | [0, 100] |
Must have same length as inputRange |
| extrapolateLeft | How to handle values below the input range | 'extend', 'clamp', 'identity' |
Default is 'extend' |
| extrapolateRight | How to handle values above the input range | 'extend', 'clamp', 'identity' |
Default is 'extend' |
Example: Basic Interpolation
import { interpolate } from 'react-native';\n\nconst value = new Animated.Value(0);\nconst interpolated = value.interpolate({\n inputRange: [0, 1],\n outputRange: [0, 100]\n});
Example: Color Interpolation
const color = animatedValue.interpolate({\n inputRange: [0, 1],\n outputRange: ['#ff0000', '#00ff00']\n});
4. Using Derived Values
Derived values in Expo animations allow you to create dynamic animations based on the values of other animated properties. They are particularly useful for creating complex animations that respond to user interactions or other animated values.
| Property | Description | Usage |
|---|---|---|
| derivedValue | Represents a value that is derived from another animated value. | |
| useDerivedValue | Hook to create a derived animated value. | |
Example: Using Derived Values for Scaling
import { useAnimatedStyle, useDerivedValue } from 'react-native-reanimated';
const scaleValue = useDerivedValue(() => {
return animatedValue.value * 1.5;
});
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [{ scale: scaleValue.value }],
};
});
Example: Combining Derived Values
import { useAnimatedStyle, useDerivedValue } from 'react-native-reanimated';
const offsetX = useDerivedValue(() => {
return animatedValue.value * 10;
});
const offsetY = useDerivedValue(() => {
return animatedValue.value * 5;
});
const animatedStyle = useAnimatedStyle(() => {
return {
transform: [
{ translateX: offsetX.value },
{ translateY: offsetY.value },
],
};
});
Note: Derived values are recalculated on every frame, so avoid heavy computations inside the derived value function to maintain performance.
5. Animating Colors
| Property | Values | Description |
|---|---|---|
| color | "#FF0000", "red", "rgb(255, 0, 0)" |
Color value to animate |
| duration | 300 |
Animation duration in milliseconds |
| easing | "ease-in-out" |
Easing function for animation |
Example: Animating Color with Easing
import { Animated } from 'react-native';
const AnimatedColor = () => {
const colorAnimation = new Animated.Value(0);
Animated.loop(
Animated.sequence([
Animated.timing(colorAnimation, {
toValue: 1,
duration: 1000,
easing: Animated.Easing.easeInOut,
}),
Animated.timing(colorAnimation, {
toValue: 0,
duration: 1000,
easing: Animated.Easing.easeInOut,
}),
])
).start();
const backgroundColor = colorAnimation.interpolate({
inputRange: [0, 1],
outputRange: ['#FF0000', '#00FF00'],
});
return (
<Animated.View
style={{
width: 100,
height: 100,
backgroundColor,
}}
>
</Animated.View>
);
};
6. Creating Custom Easing
| Easing Function | Description | Usage |
|---|---|---|
| Easing.functionName | Predefined easing function from React Native Animated | Animated.Easing.linear |
| Easing.custom | Custom easing function using a cubic Bezier curve | Easing.custom((t) => t * t) |
Example: Custom Easing Function
import { Animated } from 'react-native';\n\nconst customEasing = (t) => {\n return t * t;\n};\n\nconst animatedValue = new Animated.Value(0);\nAnimated.timing(animatedValue, {\n toValue: 1,\n duration: 1000,\n easing: customEasing,\n}).start();
Note: Custom easing functions must return a value between 0 and 1 for any input between 0 and 1.
7. Using Animation Callbacks
| Callback Type | Description | Usage | Notes |
|---|---|---|---|
| onStart | Called when the animation starts | onStart={() => console.log('Animation started')} |
Useful for logging or triggering side effects |
| onEnd | Called when the animation completes or is cancelled | onEnd={(result) => console.log('Animation ended:', result.finished)} |
Result object includes finished boolean |
| onFrame | Called on every animation frame (not recommended for heavy logic) | onFrame={(frame) => console.log('Current frame:', frame)} |
Can be used for real-time updates or debugging |
Example: Using Animation Callbacks
import Animated, { useAnimatedStyle, timing } from 'react-native-animated';
const AnimatedComponent = () => {
const animation = useAnimatedStyle(() => {
return {
opacity: timing({ from: 0, to: 1 }),
transform: [{ scale: timing({ from: 0.5, to: 1 }) }]
};
});
return (
<Animated.View
style={animation}
onAnimationStart={() => console.log('Animation started')}
onAnimationEnd={(result) => {
console.log('Animation ended:', result.finished);
}}
>
<Text>Animated View</Text>
</Animated.View>
);
};
Note: Callbacks are not supported in all animation types. Ensure compatibility with the chosen animation method.
8. Implementing Spring Physics
Example: Basic Spring Configuration
import { useSpring } from 'react-native-reanimated';
const springConfig = {
damping: 10,
stiffness: 100,
mass: 1,
overshootClamping: false,
restDisplacementThreshold: 0.01,
restSpeedThreshold: 0.01,
};
const animatedValue = useSpring(0, springConfig);
| Property | Description | Default Value | Notes |
|---|---|---|---|
| damping | How much to reduce the velocity by each frame | 10 |
Higher values mean faster decay |
| stiffness | How stiff the spring is | 100 |
Higher values make the spring more rigid |
| mass | Mass of the object being animated | 1 |
Affects how quickly the spring responds |
| overshootClamping | Whether to clamp the spring at its target position | false |
Useful for preventing overshoot in UI elements |
| restDisplacementThreshold | Threshold for considering the spring at rest | 0.01 |
Used to stop animation when displacement is negligible |
| restSpeedThreshold | Speed threshold for considering the spring at rest | 0.01 |
Used to stop animation when velocity is negligible |
Note: Spring physics in React Native Reanimated is based on the
react-native-reanimated library and uses a physics engine to simulate realistic motion.
Warning: Incorrectly configured spring parameters can lead to jerky animations or infinite loops. Always test with realistic values.
9. Chaining Animations
Example: Basic Animation Chain
import { Animated } from 'react-native';\n\nconst AnimatedComponent = () => {\n const animation = new Animated.Value(0);\n\n const startAnimation = () => {\n Animated.sequence([\n Animated.timing(animation, {\n toValue: 100,\n duration: 500,\n useNativeDriver: true\n }),\n Animated.timing(animation, {\n toValue: 0,\n duration: 500,\n useNativeDriver: true\n })\n ]).start();\n };\n\n return (\n <Animated.View\n style={{\n width: 100,\n height: 100,\n backgroundColor: 'blue',\n transform: [\n { translateX: animation }\n ]\n }}\n />\n );\n};
| Animation Type | Description | Usage |
|---|---|---|
| Animated.sequence | Runs animations in sequence | Animated.sequence([anim1, anim2]) |
| Animated.parallel | Runs animations in parallel | Animated.parallel([anim1, anim2]) |
Note: Use
useNativeDriver: true for better performance.
10. Creating Repeating Animations
| Property | Description | Values | Notes |
|---|---|---|---|
| loop | Controls whether the animation loops infinitely | true / false |
Default is false |
| iterations | Number of times the animation repeats | number |
Set to -1 for infinite loop |
| direction | Defines the direction of animation playback | "normal", "reverse", "alternate" |
Default is "normal" |
Example: Basic Looping Animation
import { Animated } from 'react-native';
const AnimatedComponent = () => {
const animation = new Animated.Value(0);
Animated.loop(
Animated.timing(animation, {
toValue: 1,
duration: 1000,
useNativeDriver: true
})
).start();
const rotate = animation.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg']
});
return (
<Animated.View
style={{
transform: [{ rotate }]
}}
>
<Text>Spinning Element</Text>
</Animated.View>
);
};
Example: Alternate Direction Animation
import { Animated } from 'react-native';
const AnimatedComponent = () => {
const animation = new Animated.Value(0);
Animated.loop(
Animated.timing(animation, {
toValue: 1,
duration: 1000,
useNativeDriver: true
}),
{
iterations: 2,
direction: 'alternate'
}
).start();
const scale = animation.interpolate({
inputRange: [0, 1],
outputRange: [1, 1.5]
});
return (
<Animated.View
style={{
transform: [{ scale }]
}}
>
<Text>Scaling Element</Text>
</Animated.View>
);
};