software-mansion / software-mansion/react-native-reanimated
Blank element and wrong position after shared transition end
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 11k
- Forks
- 1.5k
- Avg merge
- 3d 4h
- Merged PRs (30d)
- 172
Description
Description
I create a project to test shared animation.
when i click new transition when old transition not end yet.
old element is blank( i think opacity is 0 )
Then, transition working wrong.
See my video:
My code:
import {NavigationContainer, useNavigation} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import React from 'react';
import {
Dimensions,
FlatList,
ListRenderItemInfo,
SafeAreaView,
StyleSheet,
TouchableOpacity,
} from 'react-native';
import {GestureHandlerRootView} from 'react-native-gesture-handler';
import Animated, {
Easing,
SharedTransition,
withSequence,
withTiming,
} from 'react-native-reanimated';
const {width} = Dimensions.get('window');
const SIZE_IMAGE = width / 3;
export type ImageType = {
id: string;
};
const dataImages = [
'https://fastly.picsum.photos/id/756/300/300.jpg?hmac=ihyfC35Qzh798wqV3x_k5A3jEaY9lRiC4w1azntXksM',
'https://fastly.picsum.photos/id/71/300/300.jpg?hmac=lavbXU_aeHIi1agvKBKJYbgbtDFTCCdGDuzngtJVQjE',
'https://fastly.picsum.photos/id/1012/300/300.jpg?hmac=FpdcKpoTxl0CZdLj7RjrTjISpiu8TtsesR9f4Fm2yOk',
'https://fastly.picsum.photos/id/794/300/300.jpg?hmac=EOGWbvHbcjble_4y30-aBz6-AcjjWyNAfFlbfmS1r9U',
'https://fastly.picsum.photos/id/634/300/300.jpg?hmac=Xydl14x40_5ZjRDqaIAqxyQcuSub_xDcabmUtuE-eD8',
'https://fastly.picsum.photos/id/862/300/300.jpg?hmac=omllSASwYQXWPO584bLQUz6GetRL0GRe-2QctRXVnJA',
'https://fastly.picsum.photos/id/3/300/300.jpg?hmac=RT2JK6MzdIgNIWoIj61uPcz8aOSOi3lu2vhnwOxs7lY',
'https://fastly.picsum.photos/id/639/300/300.jpg?hmac=dQz9oW6E7gTcgpjQvsXItRygy6Z5kL2mc5sqN8bTeRw',
'https://fastly.picsum.photos/id/840/300/300.jpg?hmac=jYWhgnilJlqSvqrNyakWLPa67a5HJcAVGKo5vbXfJWc',
'https://fastly.picsum.photos/id/994/300/300.jpg?hmac=GDm1Mpq1ylmjwx5Dv9u-l1nNEAKFDBQyanBzp7Nl4yg',
'https://fastly.picsum.photos/id/242/300/300.jpg?hmac=o4XyRlR53cSyXOhNnSoYw3pNc6AiUawAVed124gdQZs',
'https://fastly.picsum.photos/id/857/300/300.jpg?hmac=_2o0QaHplHuWOr4ETeEP5_3Wo6lgNhoxZgeb0yjFckc',
'https://fastly.picsum.photos/id/217/300/300.jpg?hmac=BsPwAcRl68EZm3jQkeJOcTySx7bzPELlYkwkkl-itpc',
'https://fastly.picsum.photos/id/1041/300/300.jpg?hmac=PosL0KGsFiR_uaOxVY5r9pvWRIyIpn07BSV53jT6We0',
'https://fastly.picsum.photos/id/858/300/300.jpg?hmac=_ejZ2a4fSroS4BO_gXXIxq7hyd0RIHSP290jgbqMO2c',
];
export type ImageExpoProps = {
image: ImageType;
};
const transition = SharedTransition.custom(values => {
'worklet';
return {
height: withTiming(values.targetHeight, {duration: 300}),
width: withTiming(values.targetWidth, {duration: 300}),
originX: withTiming(values.targetOriginX, {duration: 300}),
originY: withSequence(
withTiming(values.currentOriginY + 50, {
duration: 300,
easing: Easing.linear,
}),
withTiming(values.targetOriginY, {
duration: 500,
easing: Easing.linear,
}),
),
};
});
const ImageExpo = ({url}) => {
const navigation = useNavigation();
return (
<TouchableOpacity
onPress={() => {
navigation.navigate('Detail', {url});
}}>
<Animated.View
sharedTransitionStyle={transition}
sharedTransitionTag={`container_${url}`}
style={styles.image}>
<Animated.Image
sharedTransitionStyle={transition}
sharedTransitionTag={`image_${url}`}
resizeMode="cover"
source={{uri: url}}
style={StyleSheet.absoluteFillObject}
/>
</Animated.View>
</TouchableOpacity>
);
};
const ListImage = () => {
// func
const renderImage = ({item}: ListRenderItemInfo<string>) => {
return <ImageExpo url={item} />;
};
const keyExtractor = (item: string) => {
return item;
};
// render
return (
<SafeAreaView style={styles.root}>
<FlatList
numColumns={3}
renderItem={renderImage}
keyExtractor={keyExtractor}
data={dataImages}
/>
</SafeAreaView>
);
};
const DetailImage = ({
route: {
params: {url},
},
}) => {
return (
<>
<SafeAreaView style={styles.root}>
<Animated.View
sharedTransitionStyle={transition}
sharedTransitionTag={`container_${url}`}
style={styles.detailImage}>
<Animated.Image
sharedTransitionStyle={transition}
sharedTransitionTag={`image_${url}`}
resizeMode="cover"
source={{uri: url}}
style={StyleSheet.absoluteFillObject}
/>
</Animated.View>
</SafeAreaView>
</>
);
};
const Stack = createNativeStackNavigator();
const App = () => {
return (
<GestureHandlerRootView style={styles.root}>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="List" component={ListImage} />
<Stack.Screen
options={{
animation: 'slide_from_bottom',
}}
name="Detail"
component={DetailImage}
/>
</Stack.Navigator>
</NavigationContainer>
</GestureHandlerRootView>
);
};
const styles = StyleSheet.create({
root: {
flex: 1,
},
detailImage: {
width: width,
height: 200,
overflow: 'hidden',
justifyContent: 'center',
alignItems: 'center',
},
image: {
justifyContent: 'center',
alignItems: 'center',
width: SIZE_IMAGE,
height: SIZE_IMAGE,
overflow: 'hidden',
borderWidth: 1,
borderColor: '#ffffff',
borderRadius: 10,
},
});
export default App;
Steps to reproduce
- Create list image
- Navigate to detail screen
- Click back button
- Before animated end, click new screen (Detail screen)
Snack or a link to a repository
I sent my code above
Reanimated version
3.0.2
React Native version
0.71.4
Platforms
iOS
JavaScript runtime
None
Workflow
React Native (without Expo)
Architecture
Paper (Old Architecture)
Build type
Debug mode
Device
iOS simulator
Device model
No response
Acknowledgements
Yes
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the issue with the provided TypeScript example on iOS, using React Native 0.71.4 and Reanimated 3.0.2. Exercise the back-navigation path and trigger another detail transition before the first animation ends; done means the shared element is neither blank nor positioned incorrectly after the interrupted transition.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react-native, typescript
- Domain
- mobile-dev
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100