Documents
Custom Animations
Custom Animations
Type
Document
Status
Published
Created
Apr 22, 2026
Updated
Apr 22, 2026

Custom Animation#


import { Callout } from 'nextra/components'

After some effort, we finally implemented custom animation in v2, now we just need to implement a callback function of type TAnimationStyle and pass it to the customAnimation property of Carousel.

Prepare#

type TAnimationStyle = (value: number) => ViewStyle;

This function will be called in each item and accepts a parameter value indicating the position of the current item relative to window. 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} />;
    }}
/>;