react-nativecarouselreact-native-reanimated

Partial scroll effect in a React Native Carousel using react-native-reanimated-carousel


I am working with react-native-reanimated-carousel in a React Native project, and I want to create a subtle animation when the page first loads. Specifically, I want the carousel to scroll slightly to reveal just a bit of the next item and then smoothly bounce back to the initial position, where only the first item is fully visible.

I have tried using the scrollTo method, but I can't get the animation to look smooth. The current implementation either reveals too much of the next item or the bounce-back is too fast and abrupt or does not happen at all.

const carouselRef = useRef(null);

  useEffect(() => {
    const timeout = setTimeout(() => {
      if (carouselRef.current) {
        carouselRef.current.scrollTo({
          x: 0.2,
          animated: true,
          animationDuration: 1200,
          easing: Easing.out(Easing.quad),
        });

        setTimeout(() => {
          if (carouselRef.current) {
            carouselRef.current.scrollTo({
              x: 0,
              animated: true,
              animationDuration: 1200,
              easing: Easing.in(Easing.quad),
            });
          }
        }, 1300); 
      }
    }, 500);
  }, []);

  return (
    <Animated.View style={styles.wrapper}>
         <Carousel
          ref={carouselRef}
          panGestureHandlerProps={{
            activeOffsetX: [-10, 10],
          }}
          pagingEnabled
          width={ITEM_WIDTH}
          height=HEADER_HEIGHT}
          data={data}
          scrollAnimationDuration={1000}
          onProgressChange={onProgressChange}
          renderItem={({ item, index }) => (
            <Item
              active={index === activeIndex}
              item={item}
            />
          )}
        />
    </Animated.View>
  );

How can I achieve the partial right scroll?


Solution

  • For anyone wanting to achieve the same effect:

    I just created a

        const translateX = useRef(new Animated.Value(0)).current;
    

    and put in a useEffect:

         useEffect(() => {
            if (!isLoading) {
              Animated.sequence([
                Animated.timing(translateX, {
                  toValue: -50,
                  duration: 1000,
                  useNativeDriver: true,
                }),
                Animated.spring(translateX, {
                  toValue: 0,
                  duration: 2000,
                  useNativeDriver: true,
                }),
              ]).start();
            }
          }, [isLoading]);
    

    and wrapped the item rendering in the carousel in

        <Animated.View style={{ transform: [{ translateX }] }}>
           <Item active={index === activeIndex} item={item}/>
        </Animated.View>
    

    This did the animation very smooth and bouncy.