Monday, 17 October 2022

How can I make Animation Play State paused to work in React on hover

I am trying to build an image carousel with a progress bar showing the remaining time at the bottom of the image. The carousel is able to switch to the next image after the given delay, but I am unable to pause the animation on hover.

https://codesandbox.io/s/unruffled-sun-qz5d89?file=/src/Slider.tsx

import {Fragment, useEffect, useState, useCallback, useRef} from "react";
import './Slider.css';

type Props = {
    images: string[];
    slideShowDelay?: number;
}
export default function Slider({images, slideShowDelay=5}: Props): JSX.Element {
    const [currentSlide, setCurrentSlide] = useState<number>(0);
    const [timer, setTimer] = useState<NodeJS.Timer>();
    const progressRef = useRef<HTMLDivElement | null>(null);
    const [animationState, setAnimationState] = useState('animate');
    const prevButtonHandler = () => {
        setCurrentSlide(prev => {
            const result = prev-1;
            if (result < 0) {
                return images.length - 1;
            }
            return result;
        });
    }
    const nextButtonHandler = useCallback(() => {
        setCurrentSlide(prev => {
            const result = prev+1;
            if (result >= images.length) {
                return 0;
            }
            return result;
        });
    }, [images.length]);

    useEffect(() => {
        if (progressRef.current) {
            progressRef.current.style.transition = "none";
            progressRef.current.style.width = "100%";
            setTimeout(() => {
                if (progressRef.current) {
                    progressRef.current.style.width = "0%";
                    progressRef.current.style.transition = `width ${slideShowDelay}s`;
                }
            }, 50);
        }
    }, [currentSlide, slideShowDelay]);
 

    const slides = images.map((image, i) => {
        const styles = {
            transform: `translateX(${(i - currentSlide) * 100}%)`
        }
        return (<Fragment key={i}>
            <div className="slide" style={styles}>
                <img src={image} alt="random"/>
            </div>
        </Fragment>)
    });
    const mouseHandler = () => {
        setAnimationState('paused');
    }
    const mouseHandlerLeave = () => {
        setAnimationState('animate');
    }
    const transitionEndHandler = nextButtonHandler;
    const classes = `progress-bar ${animationState}`;
    const containerClasses = `slider-container ${animationState}`;
    return (
        <>
            <div className="container">
                <div className={containerClasses} onMouseEnter={mouseHandler} onMouseLeave={mouseHandlerLeave}>
                    {slides}
                    <button className="btn btn-prev" onClick={prevButtonHandler}> {"<"} </button>
                    <button className="btn btn-next" onClick={nextButtonHandler}> {">"} </button>
                    <div onTransitionEnd={transitionEndHandler} ref={progressRef} role={"progressbar"} className={classes} />
                </div>
            </div>
        </>
    )
}

What am I doing wrong here? Any help is appreciated.



from How can I make Animation Play State paused to work in React on hover

No comments:

Post a Comment