Custom Animations
Type
Document
Status
Published
Created
Apr 22, 2026
Updated
Jul 21, 2026
Updated by
Dosu Bot

Custom Animation#


import { Callout } from 'nextra/components'

Pass a worklet-compatible callback of type TAnimationStyle to the customAnimation prop.

Prepare#

import type { TAnimationStyle } from "react-native-reanimated-carousel";

const animationStyle: TAnimationStyle = (value, _index) => {
  "worklet";

  return {
    opacity: Math.max(0, 1 - Math.abs(value)),
    zIndex: Math.round(100 - Math.abs(value)),
  };
};

The callback receives value, the item's animated position relative to the viewport, and index, the item's data index. The following picture shows the relationship between value and position.

Sketch File

After getting the value, we only need to describe how the item is displayed in the corresponding position, and the rest is handed over to Animated to execute.

Don't forget to set `zIndex`

Let's get started!#

Here are a few examples.

Parallax#

![advanced-parallax](../../../assets/advanced-parallax.gif)
const animationStyle: TAnimationStyle = React.useCallback((value: number) => {
    'worklet';

    const zIndex = interpolate(value, [-1, 0, 1], [10, 20, 30]);
    const translateX = interpolate(
        value,
        [-1, 0, 1],
        [-PAGE_WIDTH * 0.5, 0, PAGE_WIDTH]
    );

    return {
        transform: [{ translateX }],
        zIndex,
    };
}, []);

<Carousel
    style={{ width: screen.width, height: 240 }}
    data={[...new Array(6).keys()]}
    customAnimation={animationStyle}
    renderItem={({ index, animationValue }) => {
        return (
            <CustomItem
                key={index}
                index={index}
                animationValue={animationValue}
            />
        );
    }}
/>;

const CustomItem = ({ index, animationValue }) => {
    const maskStyle = useAnimatedStyle(() => {
        const backgroundColor = interpolateColor(
            animationValue.value,
            [-1, 0, 1],
            ['#000000dd', 'transparent', '#000000dd']
        );

        return {
            backgroundColor,
        };
    }, [animationValue]);

    return (
        <View style={{ flex: 1 }}>
            <SBItem key={index} index={index} style={{ borderRadius: 0 }} />
            <Animated.View
                pointerEvents="none"
                style={[
                    {
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        right: 0,
                        bottom: 0,
                    },
                    maskStyle,
                ]}
            />
        </View>
    );
};

In order to implement some animation effects outside Carousel, such as MaskView, we pass the animation value calculated inside each Item to the outside through renderItem.

ScaleFadeInOut#

![scale-fade-in-out](../../../assets/scale-fade-in-out.gif)
const animationStyle: TAnimationStyle = React.useCallback((value: number) => {
    'worklet';

    const zIndex = interpolate(value, [-1, 0, 1], [10, 20, 30]);
    const scale = interpolate(value, [-1, 0, 1], [1.25, 1, 0.25]);
    const opacity = interpolate(value, [-0.75, 0, 1], [0, 1, 0]);

    return {
        transform: [{ scale }],
        zIndex,
        opacity,
    };
}, []);

<Carousel
    style={{
        width: screen.width * 0.7,
        height: 240 * 0.7,
        justifyContent: 'center',
        alignItems: 'center',
    }}
    data={[...new Array(6).keys()]}
    customAnimation={animationStyle}
    renderItem={({ index }) => {
        return <SBItem key={index} index={index} />;
    }}
/>;