software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
8.98k stars 1.3k forks source link

Blank element and wrong position after shared transition end #4237

Open ngocle2497 opened 1 year ago

ngocle2497 commented 1 year ago

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:

https://user-images.githubusercontent.com/43195241/225859358-9903a559-dd62-4b8c-99a3-27d1b62c956e.mp4

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

  1. Create list image
  2. Navigate to detail screen
  3. Click back button
  4. 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

github-actions[bot] commented 1 year ago

Hey! 👋

The issue doesn't seem to contain a minimal reproduction.

Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?

Laityned commented 3 months ago

+1 for the blank part of the issue

VladimirTomko commented 1 month ago

+1

BearyDevs commented 1 month ago