Last active
December 30, 2022 08:48
-
-
Save drewandre/6ef76e1c8a9328db496d6aba8d60a9a3 to your computer and use it in GitHub Desktop.
Pagination component for use with react-native-snap-carousel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from 'react' | |
import { StyleSheet } from 'react-native' | |
import Animated, { | |
Extrapolate, | |
interpolate, | |
useAnimatedStyle | |
} from 'react-native-reanimated' | |
import { colors, metrics } from 'styles'; | |
function clamp(value, lowerBound, upperBound) { | |
'worklet' | |
return Math.min(Math.max(lowerBound, value), upperBound); | |
}; | |
const DEFAULT_SIZE = 15 | |
function AnimatedDot({ | |
index, | |
style, | |
progress, | |
multiplier, | |
scaleDots | |
}) { | |
const animatedStyles = useAnimatedStyle(() => { | |
const opacity = interpolate( | |
clamp(progress.value, 0, 1 - multiplier), | |
[ | |
(index * multiplier) - multiplier, | |
index * multiplier, | |
(index * multiplier) + multiplier | |
], | |
[0.25, 1, 0.25], | |
Extrapolate.CLAMP | |
) | |
return { | |
opacity, | |
transform: [ | |
{ | |
scale: scaleDots | |
? interpolate( | |
opacity, | |
[0.25, 1], | |
[0.5, 1] | |
) | |
: 1 | |
} | |
] | |
} | |
}) | |
return ( | |
<Animated.View | |
key={`onboarding-pagination-dot-${index}`} | |
style={[style, animatedStyles]} | |
/> | |
) | |
} | |
export function Pagination({ | |
progress, | |
numberOfPages, | |
scaleDots = false, | |
dotStyles = {}, | |
containerStyles = {}, | |
size = 'medium' | |
}) { | |
const multiplier = 1 / numberOfPages | |
function returnSize() { | |
switch (size) { | |
case 'small': | |
return { | |
width: DEFAULT_SIZE * 0.6, | |
height: DEFAULT_SIZE * 0.6, | |
} | |
case 'large': | |
return { | |
width: DEFAULT_SIZE * 1.2, | |
height: DEFAULT_SIZE * 1.2, | |
} | |
default: | |
return { | |
width: DEFAULT_SIZE, | |
height: DEFAULT_SIZE, | |
} | |
} | |
} | |
function renderDots() { | |
let dots = [] | |
for (let i = 0; i < numberOfPages; i++) { | |
dots.push( | |
<AnimatedDot | |
key={`pagination-${i}`} | |
index={i} | |
scaleDots={scaleDots} | |
multiplier={multiplier} | |
progress={progress} | |
size={size} | |
style={[ | |
styles.dotStyle, | |
dotStyles, | |
returnSize() | |
]} | |
/> | |
) | |
} | |
return dots | |
} | |
return ( | |
<View style={[ | |
styles.dotContainer, | |
containerStyles, | |
]}> | |
{renderDots()} | |
</View> | |
) | |
} | |
const styles = StyleSheet.create({ | |
dotContainer: { | |
flex: 1, | |
paddingHorizontal: metrics.padding, | |
flexDirection: 'row', | |
alignSelf: 'center' | |
}, | |
dotStyle: { | |
width: DEFAULT_SIZE, | |
height: DEFAULT_SIZE, | |
borderRadius: 50, | |
marginHorizontal: 5, | |
backgroundColor: colors.white, | |
}, | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment