UNPKG

react-native-momentum-carousel

Version:

A React Native carousel component enables smooth and interactive image or content sliders with swiping capabilities. Ideal for showcasing multiple items or images in a compact space, this carousel can be customized with features like infinite scrolling, p

153 lines (143 loc) 6.88 kB
"use strict"; import { useMemo } from 'react'; import { useAnimatedStyle, interpolate, Extrapolation } from 'react-native-reanimated'; /** * useLayoutStackAnimation calculates the animated style for a stack-style carousel animation. * It creates an opacity and scaling effect for each carousel item based on the scroll position (scrollX). * The items will scale down when not in the center and will move slightly to the left or right as they approach the center. */ export function useLayoutStackAnimation(data) { // Calculate the input range based on the current index and direction (vertical/horizontal) const inputRange = useMemo(() => { const currentIndex = data.info.index; return [(currentIndex - 1) * (!data.vertical ? data.itemWidth : data.itemHeight), // previous item position currentIndex * (!data.vertical ? data.itemWidth : data.itemHeight), // current item position (currentIndex + 1) * (!data.vertical ? data.itemWidth : data.itemHeight) // next item position ]; }, [data.info.index, data.itemHeight, data.itemWidth, data.vertical]); // Animated style that adjusts opacity, scale, and translation based on scroll position const animatedStyle = useAnimatedStyle(() => { return { opacity: interpolate(data.scrollX.value, // The scroll position value used to interpolate inputRange, [0.8, 1, 0.8], // Decrease opacity when items are not in the center Extrapolation.CLAMP // Prevent extrapolation beyond the defined range ), transform: [{ scale: interpolate(data.scrollX.value, inputRange, [data.inactiveScale ? data.inactiveScale : 0.8, // Scale down inactive items 1, // Scale to 1 when the item is centered data.inactiveScale ? data.inactiveScale : 0.8 // Scale back down when the item is out of focus ], Extrapolation.CLAMP) }, // Apply horizontal or vertical translation depending on the orientation !data.vertical ? { translateX: interpolate(data.scrollX.value, inputRange, [200, 0, 200], // Move items to the sides when not centered Extrapolation.CLAMP) } : { translateY: interpolate(data.scrollX.value, inputRange, [200, 0, 200], // Move items vertically when not centered Extrapolation.CLAMP) }] }; }, [data.scrollX, inputRange]); // Return the animated style that will be applied to each item return animatedStyle; } /** * useLayoutDefaultAnimation creates a default animation for carousel items. * It interpolates opacity and scaling based on the scroll position (scrollX). * The default animation scales the items and adjusts their opacity when scrolling. */ export function useLayoutDefaultAnimation(data) { // Calculate the input range based on the current index and direction (vertical/horizontal) const inputRange = useMemo(() => { const currentIndex = data.info.index; return [(currentIndex - 1) * (!data.vertical ? data.itemWidth : data.itemHeight), // previous item position currentIndex * (!data.vertical ? data.itemWidth : data.itemHeight), // current item position (currentIndex + 1) * (!data.vertical ? data.itemWidth : data.itemHeight) // next item position ]; }, [data.info.index, data.itemHeight, data.itemWidth, data.vertical]); // Animated style that adjusts opacity and scale for the default animation const animatedStyle = useAnimatedStyle(() => { return { opacity: interpolate(data.scrollX.value, // The scroll position value used to interpolate inputRange, [0.8, 1, 0.8], // Decrease opacity when items are not in the center Extrapolation.CLAMP // Prevent extrapolation beyond the defined range ), transform: [{ scale: interpolate(data.scrollX.value, inputRange, [data.inactiveScale ? data.inactiveScale : 0.8, // Scale down inactive items 1, // Scale to 1 when the item is centered data.inactiveScale ? data.inactiveScale : 0.8 // Scale back down when the item is out of focus ], Extrapolation.CLAMP) }] }; }, [data.scrollX, inputRange]); // Return the default animated style return animatedStyle; } /** * useLayoutTinderAnimation creates a Tinder-style animation for carousel items. * It includes a combination of opacity, scale, translation (X and Y), and rotation based on the scroll position (scrollX). * This creates a dynamic "card-stack" effect with items rotating and translating as they approach or leave the center. */ export function useLayoutTinderAnimation(data) { // Calculate the input range based on the current index and direction (vertical/horizontal) const inputRange = useMemo(() => { const currentIndex = data.info.index; return [(currentIndex - 1) * (!data.vertical ? data.itemWidth : data.itemHeight), // previous item position currentIndex * (!data.vertical ? data.itemWidth : data.itemHeight), // current item position (currentIndex + 1) * (!data.vertical ? data.itemWidth : data.itemHeight) // next item position ]; }, [data.info.index, data.itemHeight, data.itemWidth, data.vertical]); // Animated style that applies opacity, scale, translation, and rotation for the Tinder-like animation const animatedStyle = useAnimatedStyle(() => { return { opacity: interpolate(data.scrollX.value, // The scroll position value used to interpolate inputRange, [0.8, 1, 0.8], // Decrease opacity when items are not in the center Extrapolation.CLAMP // Prevent extrapolation beyond the defined range ), transform: [{ scale: interpolate(data.scrollX.value, inputRange, [data.inactiveScale ? data.inactiveScale : 0.8, // Scale down inactive items 1, // Scale to 1 when the item is centered data.inactiveScale ? data.inactiveScale : 0.8 // Scale back down when the item is out of focus ], Extrapolation.CLAMP) }, { // Horizontal translation for Tinder-style effect translateX: interpolate(data.scrollX.value, inputRange, [100, 0, 100], // Move the item horizontally for the "stack" effect Extrapolation.CLAMP) }, { // Vertical translation for Tinder-style effect translateY: interpolate(data.scrollX.value, inputRange, [30, 0, 0], // Move the item vertically for the "stack" effect Extrapolation.CLAMP) }, { // Rotation for Tinder-style effect rotate: interpolate(data.scrollX.value, inputRange, [22, 0, 0], // Rotate the item as it leaves the center Extrapolation.CLAMP) + 'deg' // Apply the degree of rotation }] }; }, [data.scrollX, inputRange]); // Return the animated style that creates the Tinder effect return animatedStyle; } //# sourceMappingURL=useLayoutAnimation.js.map