Examples
Stack-cards

Here is a stack-cards animation example. You can see the source code of this page here (opens in a new tab).

import * as React from "react";
import { View } from "react-native";
import Animated, {
  interpolate,
  interpolateColor,
  runOnJS,
  useAnimatedReaction,
  useAnimatedStyle,
  useSharedValue,
} from "react-native-reanimated";
import Carousel, { TAnimationStyle } from "react-native-reanimated-carousel";
 
import { Arrow, ArrowDirection } from "./Arrow";
 
import { window } from "../../constants";
 
function Index() {
  const headerHeight = 100;
  const PAGE_WIDTH = window.width;
  const PAGE_HEIGHT = window.height - headerHeight;
  const directionAnim = useSharedValue<ArrowDirection>(
    ArrowDirection.IS_VERTICAL,
  );
  const [isVertical, setIsVertical] = React.useState(true);
 
  const animationStyle: TAnimationStyle = React.useCallback(
    (value: number) => {
      "worklet";
      const translateY = interpolate(
        value,
        [-1, 0, 1],
        [-PAGE_HEIGHT, 0, 0],
      );
 
      const translateX = interpolate(
        value,
        [-1, 0, 1],
        [-PAGE_WIDTH, 0, 0],
      );
 
      const zIndex = interpolate(value, [-1, 0, 1], [300, 0, -300]);
 
      const scale = interpolate(value, [-1, 0, 1], [1, 1, 0.85]);
 
      return {
        transform: [
          isVertical ? { translateY } : { translateX },
          { scale },
        ],
        zIndex,
      };
    },
    [PAGE_HEIGHT, PAGE_WIDTH, isVertical],
  );
 
  useAnimatedReaction(
    () => directionAnim.value,
    (direction) => {
      switch (direction) {
        case ArrowDirection.IS_VERTICAL:
          runOnJS(setIsVertical)(true);
          break;
        case ArrowDirection.IS_HORIZONTAL:
          runOnJS(setIsVertical)(false);
          break;
      }
    },
    [],
  );
 
  return (
    <View style={{ flex: 1 }}>
      <Carousel
        loop
        style={{
          width: PAGE_WIDTH,
          height: PAGE_HEIGHT,
          justifyContent: "center",
          alignItems: "center",
          backgroundColor: "black",
        }}
        vertical={isVertical}
        width={PAGE_WIDTH}
        height={PAGE_HEIGHT}
        data={[...new Array(6).keys()]}
        renderItem={({ index, animationValue }) => (
          <Item
            key={index}
            index={index}
            animationValue={animationValue}
            directionAnim={directionAnim}
          />
        )}
        customAnimation={animationStyle}
      />
    </View>
  );
}
 
const Item: React.FC<{
  index: number
  animationValue: Animated.SharedValue<number>
  directionAnim: Animated.SharedValue<ArrowDirection>
}> = ({ animationValue, directionAnim }) => {
  const maskStyle = useAnimatedStyle(() => {
    const zIndex = interpolate(
      animationValue.value,
      [-1, 0, 1],
      [300, 0, -300],
    );
 
    const backgroundColor = interpolateColor(
      animationValue.value,
      [-1, 0, 1],
      ["transparent", "transparent", "rgba(0,0,0,0.3)"],
    );
 
    return {
      backgroundColor,
      zIndex,
    };
  }, [animationValue]);
 
  return (
    <View
      style={{
        backgroundColor: "white",
        flex: 1,
        borderRadius: 20,
        justifyContent: "center",
        alignItems: "center",
      }}
    >
      <Animated.View
        style={[
          maskStyle,
          { position: "absolute", width: "100%", height: "100%" },
        ]}
      />
      <Arrow directionAnim={directionAnim} />
    </View>
  );
};
 
export default Index;