dohooo / react-native-reanimated-carousel

🎠 React Native swiper/carousel component, fully implemented using reanimated v2, support to iOS/Android/Web. (Swiper/Carousel)
https://react-native-reanimated-carousel.vercel.app
MIT License
2.58k stars 293 forks source link

Image Flickers When Swiping Carousel #630

Open paulokaome opened 1 week ago

paulokaome commented 1 week ago

Description:

When swiping the carousel, the image flickers in the background. This issue occurs inconsistently, but it significantly affects the user experience.

Steps to Reproduce:

Open the app and navigate to the carousel. Swipe left or right to navigate through the images. Observe the background image flicker during the swipe action. Expected Behavior: The images should transition smoothly without any flickering.

Actual Behavior: The background image flickers when swiping through the carousel.

Versions (please complete the following information):

Captura de tela 2024-06-17 130348

dosubot[bot] commented 1 week ago

Hey @paulokaome! I'm here to help you with any bugs, questions, or becoming a contributor. Let's squash those bugs!

To address the flickering issue when swiping the carousel, you can try the following approaches:

  1. Optimize Image Loading: Ensure that the images are preloaded before they are displayed in the carousel. This can be done using the Image.prefetch method in React Native.

  2. Use a Cached Image Component: Use a library like react-native-fast-image which provides a performant <FastImage> component that supports caching and reduces flickering.

  3. Avoid Re-rendering: Ensure that the carousel component and its children are not being re-rendered unnecessarily. This can be achieved by using React.memo or useMemo to memoize components and values.

Additionally, you can use the react-native-reanimated-carousel library, which is optimized for performance and can help reduce flickering. Here is an example of how you can integrate it:

import * as React from "react";
import { Text, View, Image } from "react-native";
import { interpolate } from "react-native-reanimated";
import Carousel, { TAnimationStyle } from "react-native-reanimated-carousel";
import { BlurView } from "expo-blur";
import { faker } from "@faker-js/faker";
import { window } from "../../constants";

function Index() {
  const headerHeight = 100;
  const scale = 0.9;
  const RIGHT_OFFSET = window.width * (1 - scale);
  const ITEM_WIDTH = window.width * scale;
  const ITEM_HEIGHT = 120;
  const PAGE_HEIGHT = window.height - headerHeight;
  const PAGE_WIDTH = window.width;

  const animationStyle: TAnimationStyle = React.useCallback(
    (value: number) => {
      "worklet";
      const translateY = interpolate(
        value,
        [-1, 0, 1],
        [-ITEM_HEIGHT, 0, ITEM_HEIGHT],
      );
      const right = interpolate(
        value,
        [-1, -0.2, 1],
        [RIGHT_OFFSET / 2, RIGHT_OFFSET, RIGHT_OFFSET / 3],
      );
      return {
        transform: [{ translateY }],
        right,
      };
    },
    [RIGHT_OFFSET],
  );

  return (
    <View style={{ flex: 1 }}>
      <Image
        source={{
          uri: `${faker.image.nature(PAGE_WIDTH, PAGE_HEIGHT)}?random=${Math.random()}`,
        }}
        style={{
          width: PAGE_WIDTH,
          height: PAGE_HEIGHT,
          position: "absolute",
        }}
      />
      <BlurView
        intensity={80}
        tint="dark"
        style={{
          width: PAGE_WIDTH,
          height: PAGE_HEIGHT,
          position: "absolute",
        }}
      />
      <Carousel
        loop
        vertical
        style={{
          justifyContent: "center",
          width: PAGE_WIDTH,
          height: PAGE_HEIGHT,
        }}
        width={ITEM_WIDTH}
        pagingEnabled={false}
        height={ITEM_HEIGHT}
        data={[...new Array(10).keys()]}
        renderItem={({ index }) => {
          return (
            <View key={index} style={{ flex: 1, padding: 10 }}>
              <View
                style={{
                  alignItems: "flex-start",
                  flex: 1,
                  justifyContent: "space-between",
                  flexDirection: "row",
                  borderRadius: 20,
                }}
              >
                <View
                  style={{
                    flexDirection: "row",
                    alignItems: "center",
                  }}
                >
                  <Image
                    style={{
                      width: 20,
                      height: 20,
                      borderRadius: 10,
                      marginRight: 5,
                    }}
                    source={{
                      uri: `${faker.image.animals(20, 20)}?random=${Math.random()}`,
                    }}
                  />
                  <Text
                    numberOfLines={1}
                    style={{
                      maxWidth: ITEM_WIDTH * 0.3 - 40,
                      color: "white",
                    }}
                  >
                    {faker.animal.dog()}
                  </Text>
                </View>
                <View
                  style={{
                    width: ITEM_WIDTH * 0.6,
                    height: ITEM_HEIGHT - 20,
                    borderRadius: 10,
                    overflow: "hidden",
                  }}
                >
                  <Image
                    style={{
                      width: ITEM_WIDTH * 0.6,
                      height: ITEM_HEIGHT - 20,
                      borderRadius: 10,
                      marginRight: 5,
                    }}
                    source={{
                      uri: `${faker.image.nature(Math.round(ITEM_WIDTH * 0.6), ITEM_HEIGHT - 20)}?random=${Math.random()}`,
                    }}
                  />
                </View>
              </View>
            </View>
          );
        }}
        customAnimation={animationStyle}
      />
    </View>
  );
}

export default Index;

In this example, the react-native-reanimated-carousel library is used to create a smooth and performant carousel. The BlurView component from expo-blur is used to add a blur effect to the background image, which can help in reducing the perception of flickering. The interpolate function from react-native-reanimated is used to create custom animations for the carousel items [1].

Additionally, ensure that the onConfigurePanGesture property is not causing frequent reconfigurations of the pan gesture, as this could contribute to flickering issues [2][3].

To continue talking to Dosu, mention @dosu.

pdb3616109 commented 1 week ago

Perhaps this patch can solve your problem

576