UNPKG

react-native-walkthrough-swiper

Version:

A walkthrough swiper component for React-Native. Can be used in onboarding/walkthrough screens. Uses Reanimated API to create smooth animations.

119 lines (104 loc) 2.92 kB
import React, { useEffect, useRef } from 'react'; import { I18nManager, StyleSheet, View } from 'react-native'; import Reanimated, { useAnimatedStyle, useSharedValue, withSpring, } from 'react-native-reanimated'; const SELECTED_PAGER_WIDTH = 24; const OVAL_WIDTH = 6; const PAGER_SPACE = 8; const PAGINATION_SPRING_CONFIG = { damping: 13, mass: 1, stiffness: 100, }; const Pagination = ({ data, currentSlide, inActiveSlideColor='#CFD2D4', activeSlideColor='#130C1A' }) => { const oldSlide = useRef(currentSlide); const animationVars = useRef(data.map(() => useSharedValue(0))); const selectedPos = useSharedValue(0); useEffect(() => { moveSelected(currentSlide); movePagination(oldSlide.current, currentSlide); oldSlide.current = currentSlide; }, [currentSlide]); const selectedBtnAnimatedStyle = useAnimatedStyle(() => { const transX = I18nManager.isRTL ? -1 * selectedPos.value : selectedPos.value; return { transform: [{ translateX: transX }], }; }); const moveSelected = (active) => { selectedPos.value = withSpring( active * (OVAL_WIDTH + PAGER_SPACE), PAGINATION_SPRING_CONFIG ); }; const movePagination = (prev, active) => { const displacement = I18nManager.isRTL ? SELECTED_PAGER_WIDTH + PAGER_SPACE : -1 * (SELECTED_PAGER_WIDTH + PAGER_SPACE); if (active > prev) { animationVars.current[active - 1].value = withSpring( displacement, PAGINATION_SPRING_CONFIG ); } else { animationVars.current[active].value = withSpring( 0, PAGINATION_SPRING_CONFIG ); } }; return ( <View style={styles.components}> {data.map((_, index) => { const style = index === 0 ? [styles.selected, {backgroundColor:activeSlideColor}] : [styles.oval, {backgroundColor:inActiveSlideColor}]; return ( <Reanimated.View key={index} style={[ style, index === 0 ? selectedBtnAnimatedStyle : useAnimatedStyle(() => { const transX = animationVars.current[index - 1].value; return { transform: [{ translateX: transX }], }; }), ]} /> ); })} </View> ); }; export default React.memo(Pagination); const styles = StyleSheet.create({ components: { position: 'absolute', height: 6, bottom: 40, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', alignSelf: 'center', }, selected: { width: SELECTED_PAGER_WIDTH, height: 6, borderRadius: 3, marginHorizontal: 4, backgroundColor: '#130C1A', }, oval: { width: OVAL_WIDTH, height: 6, borderRadius: 3, marginHorizontal: 4, backgroundColor: '#CFD2D4', }, });