画面間の要素のアニメーション
このガイドでは、画面間で要素をアニメーション化する方法について説明します。この機能は、共有要素トランジションとして知られており、@react-navigation/native-stack
にReact Native Reanimatedと共に実装されています。
このガイドの執筆時点では、共有要素トランジションは実験的な機能と見なされており、本番環境での使用は推奨されていません。
前提条件
このガイドを続ける前に、アプリが以下の条件を満たしていることを確認してください
@react-navigation/native-stack
を使用していること。共有要素トランジション機能は、JSベースの@react-navigation/stack
ではサポートされていません。react-native-reanimated
のv3.0.0以上がインストールおよび構成されていること。
最小限の例
共有トランジションを作成するには
react-native-reanimated
からインポートされたAnimated
コンポーネントを使用します。- 異なる画面上の要素に同じ
sharedTransitionTag
を割り当てます。 - 画面間を移動します。トランジションは自動的に開始されます。
import * as React from 'react';
import { View, Button, StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import Animated from 'react-native-reanimated';
const Stack = createNativeStackNavigator();
function HomeScreen({ navigation }) {
return (
<View style={styles.container}>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
<Animated.Image
source={{ uri: 'https://picsum.photos/id/39/200' }}
style={{ width: 300, height: 300 }}
sharedTransitionTag="tag"
/>
</View>
);
}
function DetailsScreen({ navigation }) {
return (
<View style={styles.container}>
<Button title="Go back" onPress={() => navigation.goBack()} />
<Animated.Image
source={{ uri: 'https://picsum.photos/id/39/200' }}
style={{ width: 100, height: 100 }}
sharedTransitionTag="tag"
/>
</View>
);
}
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
},
});
sharedTransitionTag
は、単一の画面のコンテキスト内で一意である必要がある文字列ですが、画面間の要素を一致させる必要があります。このプロップにより、Reanimatedは要素を識別してアニメーション化できます。これは、key
プロパティと同様に、Reactにリスト内のどの要素がどれであるかを伝える役割を果たします。
トランジションのカスタマイズ
デフォルトでは、トランジションはwidth
、height
、originX
、originY
、およびtransform
プロパティをwithTiming
を使用して500ミリ秒の期間でアニメーション化します。width
、height
、originX
、およびoriginY
プロパティは簡単にカスタマイズできます。transform
のカスタマイズも可能ですが、このガイドの範囲を大きく超えています。
カスタムSharedTransition APIは最終決定されておらず、今後のリリースで変更される可能性があります。
トランジションをカスタマイズするには、transform
以外のすべてのプロパティを渡す必要があります。
import { SharedTransition } from 'react-native-reanimated';
const customTransition = SharedTransition.custom((values) => {
'worklet';
return {
height: withSpring(values.targetHeight),
width: withSpring(values.targetWidth),
originX: withSpring(values.targetOriginX),
originY: withSpring(values.targetOriginY),
};
});
function HomeScreen() {
return (
<Animated.Image
style={{ width: 300, height: 300 }}
sharedTransitionTag="tag"
sharedTransitionStyle={customTransition} // add this to both elements on both screens
/>
);
}
リファレンス
完全な共有要素トランジションのリファレンスは、React Native Reanimatedのドキュメントにあります。
代替案
または、react-native-shared-element
ライブラリと、JSベースの@react-navigation/stack
ナビゲーターで共有要素トランジションを実装するReact Navigationバインディングを使用することもできます。ただし、このソリューションは積極的にメンテナンスされていません。
react-native-navigation
も共有要素トランジションのサポートを備えています。詳細については、こちらをご覧ください。