Native shared element transition primitives for react-native 💫
yarn add react-native-shared-element
Link the native code (TODO: Update for auto-linking)
react-native link react-native-shared-element
import { SharedElement, SharedElementTransition } from 'react-native-shared-element';
// Scene 1
let startNode;
<View>
...
<SharedElement onNode={node => startNode = node}>
<Image style={styles.image} source={...} />
</SharedElement>
...
</View>
// Scene2
let endNode;
<View>
...
<SharedElement onNode={node => endNode = node}>
<Image style={styles.image} source={...} />
</SharedElement>
...
</View>
// Render overlay in front of screen
const position = new Animated.Value(0);
<View style={StyleSheet.absoluteFill}>
<SharedElementTransition
start={{node: startNode}}
end={{node: endNode}}
position={position} />
</View>
react-native-shared-element is a "primitive" that runs shared element transitions
entirely native without requiring any passes over the JavaScript bridge. It works by taking in a start- and end node, which are obtained using the <SharedElement>
component.
Whenever a transition between screens occurs (e.g. performed by a router/navigator), a view in
front of the app should be rendered to host the shared element transition. The position
prop is used to interpolate between the start- and end nodes, 0
meaning "Show the start node" and 1
meaning "Show the end node".
Whenever the <SharedElementTransition>
component is rendered, it performs the following tasks:
- Measure the size and position of the provided element
- Obtain the styles of the elements
- Obtain the visual content of the elements (e.g. an image or a view snapshot)
- Render a visual copy of the start element at its current position
- Hide the original elements whenever the visual copy are on the screen
- Monitor the
position
prop and render the shared element transition accordingly - Upon unmount, unhide the original elements
You typically do not use this component directly, but instead use a Router or Transition-engine which provides a higher-level API.
See ./Example/src/components/Router.js
for an example implementation of a simple stack router using
shared element transitions.
The <SharedElement>
component accepts a single child and returns a node
to it through the onNode
event handler. The child must be a "real" View
which exists in the native view hierarchy.
Property | Type | Description |
---|---|---|
children |
element |
A single child component, which must map to a real view in the native view hierarchy |
onNode |
function |
Event handler that sets or unsets the node-handle |
View props... |
Other props supported by View |
The <SharedElementTransition>
component executes a shared element transition natively. It natively performs the following tasks: measure, clone, hide, animate and unhide, to achieve the best results.
Property | Type | Description |
---|---|---|
start |
{ node: SharedElementNode, ancestor: SharedElementNode } |
Start node- and ancestor |
end |
{ node: SharedElementNode, ancestor: SharedElementNode } |
End node- and ancestor |
position |
`number | Animated.Value` |
animation |
SharedElementTransitionAnimation | Type of animation, e.g move start element or cross-fade between start- and end elements (default = move ) |
resize |
SharedElementTransitionResize | Resize behavior (default = auto ) |
align |
SharedElementTransitionAlign | Alignment behavior (default = auto ) |
debug |
boolean |
Renders debug overlays for diagnosing measuring and animations |
onMeasure |
function |
Event handler that is called when nodes have been measured and snapshotted |
The following animation-types are available.
Animation | Description |
---|---|
move |
Moves the start- element to the end position |
fade |
Cross-fades between the start- and end elements |
Resize-mode | Description |
---|---|
auto |
TODO. |
stretch |
Stretches the element to the same shape and size of the other element. If the aspect-ratio of the content differs, you may see stretched. In that case consider one of the other resize options. |
clip |
Do not resize, but clip the content to the size of the other content. This option is for instance useful in combination with <Text> components, where you want to reveal more text. |
none |
Do not resize the content. When combined with fade , this creates a plain cross-fade effect without any resizing or clipping |
The following alignment options are available
auto
, left-center
, left-top
, left-right
, right-center
, right-top
, right-right
, center-top
center-center
, center-bottom
The example app is located in ./Example
and serves as an exploration and testing tool. It features a simple stack router which implements the shared element primitives.
Shared element transition library is licensed under The MIT License.
This project is supported by amazing people from Expo.io