question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How should I control the opacity of carousel pagination?

See original GitHub issue

Description

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

Screenshot 2020-11-19 at 21 51 39

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:closed
  • Created 3 years ago
  • Comments:7 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
drewandrecommented, Dec 1, 2020

No problem, you could also look at react-native-animated-pagination-dots which was released a couple weeks ago.

0reactions
nelsonprsousacommented, Dec 1, 2020

Thank you very much @drewandre, it’s working perfectly! 🚀

Read more comments on GitHub >

github_iconTop Results From Across the Web

Bootstrap carousel pagination with previous and next
I am trying to add carousel Left and Right controls in the carousel-indicators list to look like pagination, it's working fine there, ...
Read more >
Carousel · Bootstrap v5.0
Carousels don't automatically normalize slide dimensions. As such, you may need to use additional utilities or custom styles to appropriately size content.
Read more >
Basics of Scroll/ carousel interaction in Figma - YouTube
Source file https://www.figma.com/community/file/982727754440876794/High-fidelity-interactive-prototypes--Part2 Join our mentorship ...
Read more >
Carousel · Boosted v5.2
Carousels don't automatically normalize slide dimensions. As such, you may need to use additional utilities or custom styles to appropriately size content. The ......
Read more >
Pagination dots when paged scrolling area is NOT full screen
I want the opacity of the pagination dots to shift when the carousel pages left or right. I know how to do this...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found