A helper library for react-native-shared-element. Works as a standalone animator or can be coupled with any navigation library.
When new scene becomes active, orchestrator will check if there are matching shared elements (by ids) between new scene and previously active scene. For each found element it will create a transition. Additionally the scenes can animate themselves during scene transition (using sceneInterpolator
prop). When scene is deactivated, orchestrator will try to find the previously active scene, and repeat the same process.
Provides context for scenes, observes scenes changes, renders transitions between scenes. By default it stretches to parent container, as it is meant to be inserted somewhere at the root app level, but it can also be placed somewhere else and styled accordingly.
Props |
|
---|---|
style? |
default {...StyleSheet.absoluteFillObject, zIndex: 99999999} |
duration? |
default 500 Scene transition duration. |
easing? |
default Easing.out(Easing.exp) Scene transition easing function. |
useNativeDriver? |
default true Change to false if your style interpolators require it. |
animation? |
default move SharedElementAnimation |
resize? |
default auto SharedElementResize |
align? |
default auto SharedElementAlign |
Provides context for elements, observes elements changes, optionally animates itself during scene transitions
Props |
|
---|---|
style? |
default undefined Outer View style. |
containerStyle? |
default undefined Inner View style, sceneInterpolator applies to this one. |
isActive? |
default false true - Scene is added to the top of the active scenes stack.false - Scene is removed from the active scenes stack.Changing this value will trigger Orchestrator search for previous scene and matching elements to run transitions. Normally this stays true for all Scenes, and is flipped to false before Scene is unmounted to trigger reverse animations |
sceneInterpolator? |
default undefined Allows animating Scene transitions, e.g: sceneInterpolator={(progress) => ({ opacity: progress })} |
mountActivationDebounce? |
default 100 How long to wait for elements to mount, before allowing scene to activate. This delays the scene's appearance, but gives time for all SharedElements to mount and layout to settle. This is not always needed, so you can try setting it to 0 if activation delay is unwanted. The default value 100 is enough for <FlatList/> with initialScrollIndex set, like in the example project |
onTransitionEnd? |
default undefined Will be called for activated scene when transition fully ends (progress becomes 1) |
Wraps the views you want to apply shared transition to.
Props |
|
---|---|
id |
required ID used for matching Elements between Scenes |
style? |
default undefined View style. |
zIndex? |
default 0 zIndex of transition that will run for this element. Used for controlling how transitions overlay each other, e.g. when Image has an Icon on top of it, both would be wrapped with different SharedTransitionElements with Icon having a higher zIndex |
npm i react-native-shared-element react-native-shared-element-orchestrator react-native-screens
# if iOS
cd ios
pod install
const App = () => {
...
return (
<SharedTransitionOrchestrator>
<Gallery .../>
{selectedMedia && <MediaViewer .../>}
</SharedTransitionOrchestrator>
)
}
const Gallery = () => {
return (
<SharedTransitionScene isActive>
{media.map(mediaUrl => {
return (
<SharedTransitionElement id={mediaUrl}>
...
</SharedTransitionElement>
)
})}
</SharedTransitionScene>
)
}
const MediaViewer = () => {
const [isActive, setIsActive] = useState(true);
const dismiss = async () => {
setIsActive(false);
setTimeout(() => {
// allow view to close with transition before unmounting
clearSelectedMedia();
}, ANIMATION_DURATION)
}
return (
<SharedTransitionScene
sceneInterpolator={(progress) => ({ opacity: progress })}
isActive={isActive}
style={{
backgroundColor: 'black',
...StyleSheet.absoluteFillObject
}}
>
<SharedTransitionElement id={selectedMediaUrl}>
...
</SharedTransitionElement>
</SharedTransitionScene>
)
}
Usage with navigation libraries is also possible. Scenes can be placed inside screens, and sceneInterpolator
can be left empty. isActive
can then be toggled off when the screen is being popped out of the screen stack, e.g. beforeRemove
event in React Navigation