Animation Model
Screen transitions in react-native-screen-transitions are driven by a continuousprogress value that flows through a worklet function called screenStyleInterpolator.
The progress value represents the animation state:
- 0 = Screen B is fully visible (before transition begins)
- 0–1 = Transition in progress (Screen A visible → Screen B visible)
- 1 = Screen A is fully hidden, Screen B is fully visible
- 1–2 = Dismissal in progress (Screen B returns to Screen A)
- 2 = Back at original state
Slot-Based Return Format
Custom animations use a modular slot-based return format that separates concerns:| Slot | Purpose | Type |
|---|---|---|
content | Main screen content layer | { style: StyleProp<ViewStyle> } |
backdrop | Semi-transparent backdrop/dimming | { style: StyleProp<ViewStyle> } |
surface | Custom surface layer (with surfaceComponent) | { style: ..., props: ... } |
["id"] | Custom elements registered with styleId | { style: StyleProp<ViewStyle> } |
style and optional props to pass to the underlying component.
Basic Opacity Fade
Here’s a simple fade transition:Transform Animations
Combine multiple transforms for complex motion:Dismissal Animation (Progress 1–2)
Control what happens when the user drags to dismiss:Interpolator Props
Your interpolator function receives an object with these properties:| Prop | Type | Description |
|---|---|---|
progress | Animated.SharedValue<number> | Current animation progress (0–2) |
bounds | (options) => BoundsResult | Function to query shared element bounds |
layouts | { content?: LayoutRect } | Measured layout dimensions |
isReverse | boolean | True if this is a dismissal (progress 1–2) |
Progress Interpolation
Use Reanimated’sinterpolate to map progress to animation values:
Layout-Aware Animations
Access measured layout dimensions to create responsive animations:"auto", layouts.content.height contains the intrinsic content height.
Shared Element Animations with Bounds
Thebounds() function queries the animation state of shared elements:
Bounds Result Object
Thebounds() function returns:
Navigation Zoom
Animate a shared element from its source position to fullscreen:Deferred First Frames
Return"defer" to delay animation startup until bounds are available:
Conditionals and Logic
Interpolators are worklets, so you can use normal JavaScript:Style ID for Individual Elements
Animate specific elements within a screen usingstyleId:
Performance Optimization
Use Reanimated Utilities
Always use Reanimated functions inside worklets:Avoid Excessive Recalculations
Cache frequently used values:Minimize Shader Compilation
Complex animations trigger more shader compilation. Keep transforms simple when possible.Troubleshooting
Animation Jumps or Jitters
Ensure you’re usinginterpolate and not JavaScript conditionals:
Layout Not Available
Iflayouts.content is undefined, you may need to measure the content. Use "defer" to wait:
Bounds Snapshot Null
Shared elements may not be measured yet. Usebounds.getSnapshot() to check:
Next Steps
- Explore shared elements for complex bounds animations
- Learn gesture coordination to make animations interactive
- See snap points for sheet-specific animations
