0

I made an auto-slide with requestAnimationFrame (RFA), I have 2 slides appearing after each other, not appear the same time. This works fine only when I always at current tab. If I click another tab then come back the current tab, it seems the slides is mixed, it appear together. It seems that the animation is paused at the time I clicking other tab. I have to wait for a few second then It will work fine again. I used browser Chrome, Firefox and Edge, all have same issue. Before using RFA, I have tried the setInterval but then saw setInterval is not as good as RFA so I use RFA. Can you give me any advice for this issue? You can see the demo here: https://repl.it/repls/SelfassuredOverjoyedGlitch#index.html

        const slide_1 = document.getElementById("top-slide-1");
        const slide_2 = document.getElementById("top-slide-2");
        var startTime;

        // SLIDE 1
        const $behindImage = $("#behind-img");
        const $frontImg = $("#front-img");
        const $topSlideTitle = $("#top-slide-1__title");
        const $topSlideTemplate = $("#top-slide-1__template");
        const $topSlideResponsive = $("#top-slide-1__responsive");
        const $topSlideButton = $("#top-slide-1__button");
        var setTimeoutSlide1;
        var setTimeoutSlide2;
        function top_slide_1(){
            slide_1.style.zIndex = 1000;
            slide_2.style.zIndex = 0;
            startTime = new Date().getTime();
            $behindImage.animate({
                "right": 370
            }, 500, "swing", function () {
                    $frontImg.animate({
                        "right": 230
                    }, 500, "swing", function (){
                        $topSlideTitle.animate({
                            "top": 65
                        }, 300, "swing", function (){
                            $topSlideTemplate.animate({
                                "left": 205
                            }, 300, "swing", function(){
                                $topSlideResponsive.animate({
                                    "left": 205
                                }, 300, "swing", function (){
                                    $topSlideButton.animate({
                                        "top": 260
                                    }, 300, "swing", function(){
                                        $topSlideButton.animate({
                                            "top": 340 
                                        }, 50, "swing", function (){
                                            $topSlideButton.animate({
                                                "top": 300 
                                            }, 100, "swing", () => {
                                                setTimeoutSlide1 = setTimeout(() => {
                                                    $behindImage.animate({
                                                        "right": "-100%"
                                                    }, 300);
                                                    $frontImg.animate({
                                                        "right": "-100%"
                                                    }, 300);
                                                    $topSlideTitle.animate({
                                                        "top": "-100%"
                                                    }, 300);
                                                    $topSlideTemplate.animate({
                                                        "left": "-100%"
                                                    }, 300);
                                                    $topSlideResponsive.animate({
                                                        "left": "100%"
                                                    }, 300);
                                                    $topSlideButton.animate({
                                                        "top": "100%"
                                                    }, 300)
                                                }, 3000)
                                            })
                                        })
                                    })
                                })
                            })
                        })
                    })
                })
        }
        // END SLIDE 1
        // SLIDE 2 
        const $behindImage2 = $("#behind-img-2");
        const $frontImg2 = $("#front-img-2"); 
        const $topSlide2Title = $("#top-slide-2__title");
        const $topSlide2Color = $("#top-slide-2__color");
        const $topSlide2Structure = $("#top-slide-2__structure");
        const $topSlide2Customize = $("#top-slide-2__customize");
        const $topSlide2Everything = $("#top-slide-2__everything");
        function top_slide_2(){
            slide_1.style.zIndex = 0;
            slide_2.style.zIndex = 1000;
            startTime = new Date().getTime();
            $behindImage2.animate({
                right: 560
            }, 300, "swing", function (){
                $frontImg2.animate({
                    bottom: 30
                }, 300, "swing", function (){
                    $topSlide2Title.animate({
                        top: 100
                    }, 300, "swing", function(){
                        $topSlide2Color.animate({
                            top: 190
                        }, 300);
                        $topSlide2Structure.animate({
                            top: 235
                        }, 500);
                        $topSlide2Customize.animate({
                            top: 280
                        }, 800, "swing", function (){
                            $topSlide2Everything.animate({
                                top: 350
                            }, 300, "swing", function (){
                                setTimeoutSlide2 = setTimeout(() => {
                                    $behindImage2.animate({right: "-100%"}, 200);
                                    $frontImg2.animate({bottom: "-100%"}, 200);
                                    $topSlide2Title.animate({top: "-100%"}, 200);
                                    $topSlide2Color.animate({top: "-100%"}, 200);
                                    $topSlide2Structure.animate({top: "-100%"}, 200);
                                    $topSlide2Customize.animate({top: "-100%"}, 200);
                                    $topSlide2Everything.animate({top: "100%"}, 200);
                                }, 3700)
                            })
                        })
                    }) 
                })
            })
        }
        top_slide_1(); // default when page load
        let counter = 1;
        let runTopSlide = function (){
            let currentTime = new Date().getTime();
            let passedTime = currentTime - startTime;
                 if (passedTime >= 6200){
                    console.log(passedTime);
                    counter += 1;
                    if (counter > 2) {counter = 1};
                    if (counter === 1) {
                        top_slide_1();
                    } else top_slide_2();
                }
            window.requestAnimationFrame(runTopSlide)
        }
        runTopSlide();
vanminhquangtri
  • 145
  • 1
  • 9
  • Can you turn this into a snippet which we can test out? – Emiel Zuurbier Sep 24 '20 at 10:29
  • I have just add the link of demo the question. Could you please see that instead. Because, at this moment I really don't know how to turn it to snippet on this website, I am sorry. https://repl.it/repls/SelfassuredOverjoyedGlitch#index.html – vanminhquangtri Sep 24 '20 at 10:34
  • This behavior is typical of browsers, here you will find the reason: [`StackOverflow Answer`](https://stackoverflow.com/a/16033979/4031083). As a suggestion, you can stop and restart your animations with specific `window` events: [`StackOverflow Answer`](https://stackoverflow.com/a/1760268/4031083). – Baro Sep 24 '20 at 10:45

2 Answers2

1

Based on my comment

This behavior is typical of browsers, here you will find the reason: StackOverflow Answer. As a suggestion, you can stop and restart your animations with specific window events: StackOverflow Answer.

This is the main edited code at the END of the page

        let counter = 1;
        let runTopSlide = function (){
            let currentTime = new Date().getTime();
            let passedTime = currentTime - startTime;
                 if (passedTime >= 6200){
                    console.log(passedTime);
                    counter += 1;
                    if (counter > 2) {counter = 1};
                    if (counter === 1) {
                        top_slide_1();
                    } else top_slide_2();
                }
            requestID = window.requestAnimationFrame(runTopSlide) // <--- Edited
        }

        var requestID; // <--- New variable
        runTopSlide();


        // --- Two new events ---
        $(window).focus(function() {
            $.fx.off = false;
            runTopSlide();
        });

        $(window).blur(function() {
            $.fx.off = true;
            window.cancelAnimationFrame(requestID);
        });
        
    </script>
  </body>
</html>
Baro
  • 5,300
  • 2
  • 17
  • 39
  • Many thanks Baro, it works perfectly, I'm going to digest you idea now. – vanminhquangtri Sep 24 '20 at 13:36
  • @vanminhquangtri I'm glad I helped. Remember to flag the correct answer. – Baro Sep 24 '20 at 13:46
  • Hello Baro, I found that some times this solution still not work fine. I think I should try another approach such as animate.css library. But my priority is still using JS to create animation. You're very nice. – vanminhquangtri Sep 26 '20 at 07:17
0

Use the Page Visiblity API. Listen to the visibilitychange event on the document to pause or unpause your animation.

I'd suggest that you switch to CSS animations to get control over starting and stopping and get more performant animations.

The demo below shows an example of the Page Visiblity API which pauses the animation when another tab is active by adding a class. This class sets the animation-play-state to paused and halts the animation.

const shape = document.querySelector('.shape');

document.addEventListener('visibilitychange', event => {
   shape.classList.toggle('pause', document.hidden);
});
.shape {
  display: block;
  width: 100px;
  height: 100px;
  background-color: blue;
  animation: shape-change 5s forwards infinite ease-in-out;
}

.shape.pause {
  animation-play-state: paused;
}

@keyframes shape-change {
  0% {
    transform: translate3d(0, 0, 0);
    background-color: red;
  }
  25% {
    transform: translate3d(300px, 0, 0);
    background-color: green;
    border-radius: 50px 0px 50px 0px;
  }
  50% {
    transform: translate3d(300px, 100px, 0) rotate(90deg);
    background-color: purple;
    border-radius: 50px 100px;
  }
  75% {
    transform: translate3d(0, 100px, 0) rotate(180deg);
    background-color: yellow;
    border-radius: 100px 100px 25px 25px;
  }
  100% {
    transform: translate3d(0, 0, 0) rotate(360deg);
    background-color: red;
  }
}
<div class="shape"></div>
Emiel Zuurbier
  • 19,095
  • 3
  • 17
  • 32