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.85k stars 329 forks source link

vertical-stack and right snapDirection shows reversed order. #663

Open sohuichoi opened 2 months ago

sohuichoi commented 2 months ago

Describe the bug When I set the snapDirection to right, the card shows reversed order when swiping to right. As shown on the demo, When it's set to left, each cards match the data's order, 0,1,2,3,4,5... But if I set it to right, the cards show 5,4,3,2,1... which is reversed order.

To Reproduce Steps to reproduce the behavior: It could be checked in the demo website.

Expected behavior I want regardless of the direction, the cards show according to the data's order, not reversed. Screenshots

Sep-06-2024 14-42-37

Versions (please complete the following information):

Smartphone (please complete the following information):

Additional context Add any other context about the problem here.

dosubot[bot] commented 2 months ago

To ensure that the cards in a vertical stack with snapDirection set to right display in the correct order instead of reversed, you need to adjust the entering animation in the renderItem function. Specifically, modify the delay calculation to account for the snapDirection being right.

Here's the updated renderItem function:

renderItem={({ index, animationValue }) => (
  <Item
    key={index}
    index={index}
    animationValue={animationValue}
    entering={FadeInRight.delay(
      snapDirection === "right" ? index * 100 : (viewCount - index) * 100,
    ).duration(200)}
  />
)}

This change ensures that the delay for the FadeInRight animation is calculated correctly based on the snapDirection [1][2].

To continue talking to Dosu, mention @dosu.

sohuichoi commented 2 months ago

@dosu How can I make Item Component for your suggesting code?

dosubot[bot] commented 2 months ago

To create the Item component for the suggested code, you can use the following implementation, incorporating elements from the SBItem component:

import React from "react";
import { View, Text, TouchableWithoutFeedback } from "react-native";
import Animated, { useAnimatedStyle, interpolate, Extrapolate } from "react-native-reanimated";
import faker from "faker";
import { SBImageItem } from "./SBImageItem"; // Assuming SBImageItem is a custom component
import { SBTextItem } from "./SBTextItem"; // Assuming SBTextItem is a custom component
import styles from "./styles"; // Assuming styles is a stylesheet
import { LongPressGestureHandler } from "react-native-gesture-handler";
import Constants from "expo-constants";

const Item: React.FC<{
  index: number;
  animationValue: Animated.SharedValue<number>;
}> = ({ index, animationValue }) => {
  const animStyle = useAnimatedStyle(() => {
    const inputRange = [index - 1, index, index + 1];
    const outputRange = [-50, 0, 50]; // Example values for translation

    return {
      transform: [
        {
          translateX: interpolate(
            animationValue.value,
            inputRange,
            outputRange,
            Extrapolate.CLAMP
          ),
        },
      ],
    };
  }, [animationValue, index]);

  const enablePretty = Constants?.expoConfig?.extra?.enablePretty || false;
  const [isPretty, setIsPretty] = React.useState(enablePretty);

  return (
    <LongPressGestureHandler
      onActivated={() => {
        setIsPretty(!isPretty);
      }}
    >
      <Animated.View
        style={[
          {
            backgroundColor: "white",
            flex: 1,
            justifyContent: "center",
            overflow: "hidden",
            alignItems: "center",
          },
          animStyle,
        ]}
      >
        {isPretty ? (
          <SBImageItem
            showIndex={false}
            key={index}
            style={styles.image}
            index={index}
          />
        ) : (
          <SBTextItem
            style={styles.text}
            index={index}
          />
        )}
        <Text
          style={{
            color: "white",
            fontWeight: "600",
            fontSize: 40,
            width: 100,
            textAlign: "center",
          }}
        >
          {faker.name.fullName().slice(0, 2).toUpperCase()}
        </Text>
      </Animated.View>
    </LongPressGestureHandler>
  );
};

export default Item;

This code defines the Item component, which takes index and animationValue as props and renders a LongPressGestureHandler component containing an Animated.View with either an SBImageItem or an SBTextItem based on the isPretty state. The animationValue prop is used to create an animated style that translates the Animated.View based on the current animation value, providing a smooth transition effect. The isPretty state toggles between showing an image or text item when the component is long-pressed [1][2][3][4].

To continue talking to Dosu, mention @dosu.

sohuichoi commented 2 months ago

it doesn't work ..