How should I control the opacity of carousel pagination?
See original GitHub issueDescription
Hi guys, I am trying react-native-reanimated 2 for the first time, so this is a n00b question for sure.
I’ve implemented this carousel and this progress indicator component, but feels like my solution is a hacky way of doing this. Basically, I am using useAnimatedScrollHandler hook on the carousel component to know what’s the current item, and using the useAnimatedStyle hook in the progress indicator component to read it. Once I read it, I can check if the index of the current item is equal to the shared value (this is the hacky way, I believe).
To avoid this, how can I calculate the opacity using the useAnimatedStyle hook? I know that useAnimatedStyle returns a AnimatedStyle component but I am not sure how I should calculate the opacity…
Code
AnimatedCarousel.tsx
const AnimatedCarousel: React.FC<IProps> = ({
items,
scale,
cardWidth,
margin,
}) => {
const scroll = useSharedValue(0);
const scrollIndicator = useSharedValue(0);
const handleScroll = useAnimatedScrollHandler({
onScroll: event => {
const current = event.contentOffset.x / (cardWidth + margin);
scroll.value = current;
scrollIndicator.value = Math.round(current); // Getting the current item (0, 1, 2, etc)
},
});
const paddingHorizontal = (theme.mixins.width - cardWidth) / 2;
return (
<>
<AnimatedScrollView
snapToInterval={cardWidth + margin}
decelerationRate="fast"
horizontal
showsHorizontalScrollIndicator={false}
onScroll={handleScroll}
scrollEventThrottle={16}
contentContainerStyle={{
paddingHorizontal,
}}
>
{items.map((item, index) => (
<AnimatedCard
title={item.title}
subtitle={item.subtitle}
imagePath={item.imagePath}
navigationProps={item.navigation}
index={index}
scroll={scroll}
scale={scale}
isLastOne={isLastOne(index, items)}
cardWidth={cardWidth}
margin={margin}
key={item.title}
/>
))}
</AnimatedScrollView>
<ProgressIndicator
numberOfItems={items.length}
scrollIndicator={scrollIndicator}
/>
</>
);
};
ProgressIndicator.tsx
type IProps = {
numberOfItems: number;
scrollIndicator: Animated.SharedValue<number>;
};
const ProgressIndicator: React.FC<IProps> = ({
numberOfItems,
scrollIndicator,
}) => {
const AnimatedStyles = (i: number): any => {
return useAnimatedStyle(() => {
return {
opacity: i === scrollIndicator.value ? 1 : 0.3, // Checking if the current item is the one to "highlight"
};
});
};
const indicators = Array(numberOfItems)
.fill({})
.map((_, i) => {
return <Dot key={i} style={[AnimatedStyles(i)]} />;
});
return <ProgressIndicatorWrapper>{indicators}</ProgressIndicatorWrapper>;
};
Possible solution?
const animatedStyle = useAnimatedStyle(() => {
return {
opacity: scrollIndicator.value, // based on the index, how should I calculate the opacity (0...1)? Basically just the 'highlighted' dot should have opacity=1
};
});
Preview
Package versions
- React: 16.13.1
- React Native: 0.63.3
- React Native Reanimated: 2.0.0-alpha.9
Thank you community 🚀
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (1 by maintainers)

Top Related StackOverflow Question
No problem, you could also look at react-native-animated-pagination-dots which was released a couple weeks ago.
Thank you very much @drewandre, it’s working perfectly! 🚀