Slide animation after resetting stop working correctly

Viewed 25

Hello! I'm trying to add slide animation to this script, everything is working fine but after reaching the limit, when index is 0 again, the photos start to disappear. I also used script to remove animation after it's done but still nothing. Also I don't see any errors in console. What can be wrong?

<!DOCTYPE html>
<html lang="en" >
<head>
  <style>

    body {
        background-color: #2b2934;
    }
            @keyframes slideInFromRight {
                0% {
                    transform: translateX(100%);
                    opacity: 0;
                }

                100% {
                    transform: translateX(0);
                    opacity: 100%;
                }
            }

            @keyframes slideItToLeft {
                0% {
                    transform: translateX(0);
                    opacity: 100%;
                }

                100% {
                    transform: translateX(-100%);
                    opacity: 0;
                }
            }

            .appear-animation {
                animation: slideInFromRight 0.5s ease-out;
            }

            .dissapear-animation {
                animation: slideItToLeft 0.5s ease-in;
            }

            [data-component="slideshow"] .slide {
                display: none;
                text-align: center;
                position: absolute;
            }

            [data-component="slideshow"] .slide.active {
                display: block;
            }
</style>

</head>
<body>

<button onclick="changeImg();">Next</button>

    <div id="slideshow-example" data-component="slideshow">
        <div role="list">
            <div class="slide">
                <img src="https://images.unsplash.com/photo-1486312338219-ce68d2c6f44d?w=752&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D" alt="">
            </div>
            <div class="slide">
                <img src="https://images.unsplash.com/photo-1488590528505-98d2b5aba04b?w=750&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D" alt="">
            </div>
            <div class="slide">
                <img src="https://images.unsplash.com/photo-1498753427761-548428edfa67?w=889&ixid=dW5zcGxhc2guY29tOzs7Ozs%3D" alt="">
            </div>
        </div>
    </div>


    <script>
        let slideshows = document.querySelectorAll('[data-component="slideshow"]');
            
        
        let index = 0;

        slideshows.forEach(initSlideShow);

        function initSlideShow(slideshow) {
            globalThis.slides = document.querySelectorAll(`#${slideshow.id} [role="list"] .slide`);
            slides[index].classList.add('active');
        };


            function changeImg() {
                slides[index].classList.add('dissapear-animation');

                var dissapear = slides[index];
                
                dissapear.addEventListener('animationend', () => {
                    dissapear.classList.remove('active');
                    dissapear.classList.remove('dissapear-animation');
                });
            

                
                index++;
                if (index == slides.length) {
                    index = 0;
                };

                slides[index].classList.add('active');
                slides[index].classList.add('appear-animation');

                var appear = slides[index];

                appear.addEventListener('animationend', () => {
                    appear.classList.remove('appear-animation');
                });

            };
    </script>

</body>
</html>
1 Answers

Your issue can be found in the changeImg function at the first animationend listener:

dissapear.addEventListener('animationend', () => {
    dissapear.classList.remove('active');
    dissapear.classList.remove('dissapear-animation');
});

Event listeners listen to an event permanently, not just within the scope of a function. Currently, your code removes the active class every single time the animationend event is fired. The solution to this is using addEventListener's once property. The below code works as expected:

dissapear.addEventListener('animationend', () => {
    dissapear.classList.remove('active');
    dissapear.classList.remove('dissapear-animation');
}, { once: true });

And just to prevent adding too many listeners, you should add the once property to the other listener as well.

appear.addEventListener('animationend', () => {
    appear.classList.remove('appear-animation');
}, { once: true });
Related