【问题标题】:animation not work correctly when tab is inactive选项卡处于非活动状态时动画无法正常工作
【发布时间】:2020-09-24 22:47:54
【问题描述】:

我使用 requestAnimationFrame (RFA) 制作了一张自动幻灯片,我有 2 张幻灯片相继出现,而不是同时出现。只有当我总是在当前选项卡时,这才有效。如果我单击另一个选项卡然后返回当前选项卡,看起来幻灯片是混合的,它一起出现。在我单击其他选项卡时,动画似乎已暂停。我必须等待几秒钟然后它会再次正常工作。我使用浏览器 Chrome、Firefox 和 Edge,都有同样的问题。 在使用 RFA 之前,我尝试过 setInterval,但后来发现 setInterval 不如 RFA,所以我使用 RFA。 你能给我关于这个问题的任何建议吗? 你可以在这里看到演示: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();

【问题讨论】:

  • 你能把它变成一个我们可以测试的sn-p吗?
  • 我刚刚添加了演示问题的链接。你能不能看看那个。因为,此刻我真的不知道如何在这个网站上把它转成sn-p,对不起。 repl.it/repls/SelfassuredOverjoyedGlitch#index.html
  • 这种行为是浏览器的典型行为,在这里你会找到原因:StackOverflow Answer。作为建议,您可以使用特定的 window 事件停止和重新启动动画:StackOverflow Answer

标签: javascript jquery animation browser setinterval


【解决方案1】:

根据我的评论

这种行为是浏览器的典型行为,在这里你会找到原因:StackOverflow Answer。作为建议,您可以使用特定的 window 事件停止和重新启动动画:StackOverflow Answer

这是页面END的主要编辑代码

        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,它运行良好,我现在要消化你的想法。
  • @vanminhquangtri 我很高兴能帮上忙。记得标记正确答案。
  • 您好 Baro,我发现有时这个解决方案仍然无法正常工作。我想我应该尝试另一种方法,例如 animate.css 库。但我的首要任务仍然是使用 JS 来创建动画。你真好。
【解决方案2】:

使用Page Visiblity API。收听document 上的visibilitychange 事件以暂停或取消暂停您的动画。

我建议您切换到 CSS 动画来控制开始和停止并获得更高效的动画。

下面的演示显示了页面可见性 API 的示例,该 API 在另一个选项卡处于活动状态时通过添加一个类来暂停动画。此类将animation-play-state 设置为paused 并停止动画。

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;
  }
}
&lt;div class="shape"&gt;&lt;/div&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-26
    • 1970-01-01
    • 1970-01-01
    • 2020-04-24
    • 2020-01-19
    • 1970-01-01
    • 2017-02-10
    • 2013-08-27
    相关资源
    最近更新 更多