切换选项卡时暂停/恢复 CSS 动画

Pause/resume CSS animations when switching tabs(切换选项卡时暂停/恢复 CSS 动画)

本文介绍了切换选项卡时暂停/恢复 CSS 动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个页面上有一堆长时间运行的 CSS 动画.我想在用户切换到另一个选项卡时暂停它们,并在用户再次返回原始选项卡时恢复它们.为简单起见,我现在的目标不是跨浏览器解决方案.让它在 Chrome 中运行就足够了.

document.addEventListener("visibilitychange", function() {如果(document.hidden){document.querySelector("#test").classList.add("paused");} 别的 {document.querySelector("#test").classList.remove("paused");}});

div#test {宽度:50px;高度:50px;背景颜色:红色;位置:绝对;左:10vw;动画名称:移动;动画持续时间:5s;动画填充模式:转发;动画定时功能:线性;}@keyframes 移动 {到 {左:90vw}}.暂停{动画播放状态:暂停!重要;-webkit-animation-play-state:暂停!重要;-moz-animation-play-state:暂停!重要;}

<div id="test"></div>

上面的代码水平移动了一个红色矩形.矩形完成动画需要 5 秒.

问题:动画开始后,切换到另一个浏览器标签;一段时间后(超过 5 秒)切换回第一个选项卡.

预期结果:矩形从其离开的点继续其路径.

实际结果:大多数情况下,矩形出现在其最终目的地并停止.有时它会按预期工作.

这意味着我无法访问 CodePen 和其他人的根窗口.因此,如果我无法访问它,我就无法向它添加任何事件侦听器.

I have a bunch of long-running CSS animations on a page. I want to pause them when a user switches to another tab and resume them when the user is back to the original tab again. For the sake of simplicity I don't aim for a cross-browser solution at this point; making it work in Chrome should be enough.

document.addEventListener("visibilitychange", function() {
  if (document.hidden) {
    document.querySelector("#test").classList.add("paused");
  } else {
    document.querySelector("#test").classList.remove("paused");    
  }
});

div#test {
  width: 50px;
  height: 50px;
  background-color: red;
  position: absolute;
  left: 10vw;
  animation-name: move;
  animation-duration: 5s;
  animation-fill-mode: forwards;
  animation-timing-function: linear;
}

@keyframes move {
  to {
    left: 90vw
  }
}

.paused {
  animation-play-state: paused !important;
  -webkit-animation-play-state: paused !important;
  -moz-animation-play-state: paused !important;
}

<div id="test"></div>

The code above moves a red rectangle horizontally. It takes 5 seconds for the rectangle to complete the animation.

The problem: after the animation starts, switch to another browser tab; after some period of time (longer than 5 seconds) switch back to the first tab.

Expected result: the rectangle continues its path from the point where it left off.

Actual result: most of the times the rectangle appears in its final destination and stops. Sometimes it works as expected. The video demonstrates the problem.

I played with different values for animation-fill-mode and animation-timing-function, but the result was always the same. As rv7 pointed out, sharing the examples in CodePen, JSFiddle, JSBin and stackoverflow JS tool affects the results, so it's better to test directly against a static page on a local HTTP server (or using links below).

For convenience I've deployed the code above to Heroku. The app is a static nodejs HTTP server, which runs on a free subscription, so it may take up to 5 minutes for the page to load for the first time. Testing results against this page:

FAIL Chrome 64.0.3282.167 (Official Build) (64-bit) Linux Debian Stretch (PC)
FAIL Chrome 70.0.3538.67 (Official Build) (64-bit) Windows 10 (PC)
FAIL Chrome 70.0.3538.77 (Official Build) (32-bit) Windows 7 (PC)
FAIL Chrome 70.0.3538.77 (Official Build) (64-bit) OSX 10.13.5 (Mac mini)
FAIL FF Quantum 60.2.2esr (64-bit) Linux Debian Stretch (PC)
OK Safari 11.1.1 (13605.2.8) (Mac mini)

The page visibility API can be replaced with window focus and blur events like this:

window.addEventListener("focus", function() {
    document.querySelector("#test").classList.remove("paused");        
});

window.addEventListener("blur", function() {
    document.querySelector("#test").classList.add("paused");
});

This replacement isn't equivalent however. If a page contains IFRAMEs, interacting with their contents will trigger focus and blur events on the main window. Executing any tab switching code in this case is not correct. This might still be an option in some cases, so I deployed a page for testing here. The results are slightly better:

FAIL Chrome 64.0.3282.167 (Official Build) (64-bit) Linux Debian Stretch (PC)
FAIL Chrome 70.0.3538.67 (Official Build) (64-bit) Windows 10 (PC)
FAIL Chrome 70.0.3538.77 (Official Build) (32-bit) Windows 7 (PC)
FAIL Chrome 70.0.3538.77 (Official Build) (64-bit) OSX 10.13.5 (Mac mini)
OK FF Quantum 60.2.2esr (64-bit) Linux Debian Stretch (PC)
OK Safari 11.1.1 (13605.2.8) (Mac mini)
This version fails more often in Chrome 64-bit than in Chrome 32-bit. In Chrome 32-bit I got just 1 failure after ~20 successful attempts. This might be related to the fact that Chrome 32-bit is installed on older hardware.

The question: is there a way to reliably pause/resume CSS animations when switching tabs?

解决方案

You can go with the focus and blur events rather than visibilitychange event because of a better browser support to the former!

let box = document.querySelector('#test');

window.addEventListener('focus', function() {
  box.style.animationPlayState = 'paused';
});

window.addEventListener('blur', function() {
  box.style.animationPlayState = 'running';
});

Alternatively, you can also do this using CSS classes:

.paused {
  animation-play-state: paused !important;
  -webkit-animation-play-state: paused !important;
  -moz-animation-play-state: paused !important;
}

let box = document.querySelector('#test');

window.addEventListener('focus', function() {
  box.classList.remove('paused');
});

window.addEventListener('blur', function() {
  box.classList.add('paused');
});

The above two ways doesn't works in the iframe of CodePen, JSFiddle, JSBin, etc; a possible reason is provided at the end of post. But, here is a video link displaying how the code works in debug mode of CodePen.

Live Example

Confirmed in:

  1. Google Chrome v70.0.3538.67 (Official Build) (32-bit)

  2. Firefox Quantum v62.0.3 (32-bit)

  3. Internet Explorer v11+


Possible reason of why the code doesn't works inside iframe:

When I tried accessing the root window (aka parent object, note that it is not the iframe window), the following error logged in the console:

And this means that I can't access the root window of CodePen and others. Therefore, if I can't access it, I can't add any event listeners to it.

这篇关于切换选项卡时暂停/恢复 CSS 动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:切换选项卡时暂停/恢复 CSS 动画

基础教程推荐