Приостановка/возобновление анимации CSS при переключении вкладок
У меня есть куча длительных анимаций CSS на странице. Я хочу приостановить их, когда пользователь переключится на другую вкладку и возобновит их, когда пользователь снова вернется к исходной вкладке. Для простоты я не нацелен на кросс-браузерное решение на данный момент; для его работы в Chrome должно быть достаточно.
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>
Ответы
Ответ 1
Вы можете перейти к событиям focus
и blur
а не к событию visibilitychange
из-за лучшей поддержки браузера первым!
let box = document.querySelector('#test');
window.addEventListener('focus', function() {
box.style.animationPlayState = 'paused';
});
window.addEventListener('blur', function() {
box.style.animationPlayState = 'running';
});
Кроме того, вы также можете сделать это с помощью классов CSS:
.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');
});
Вышеуказанные два способа не работают в iframe CodePen, JSFiddle, JSBin и т. Д.; возможная причина предоставляется в конце сообщения. Но вот видео-ссылка, показывающая, как код работает в режиме отладки CodePen.
Подтверждено в:
-
Google Chrome v70.0.3538.67 (официальная сборка) (32-разрядная версия)
-
Firefox Quantum v62.0.3 (32-разрядная версия)
-
Internet Explorer v11+
Возможная причина, по которой код не работает внутри iframe
:
Когда я попытался получить доступ к root window
(как parent
объект, обратите внимание, что это не iframe window
), в консоли было зарегистрировано следующее сообщение об ошибке:
А это означает, что я не могу получить доступ к root window
CodePen и другим. Поэтому, если я не могу получить к нему доступ, я не могу добавить к нему прослушивателей событий.
Ответ 2
Для меня ваш пример работает большую часть времени.
Однако я бы использовал проценты, а также добавлял начальную точку в ключевые кадры:
@keyframes move {
0% {
left: 0px;
}
100% {
left: 500px
}
}
Также обнаружение неактивной вкладки не срабатывает всегда. Неактивное окно работает лучше: (с помощью jQuery)
$(window).on("blur focus", function(e) {
var prevType = $(this).data("prevType");
if (prevType != e.type) {
var element = document.getElementById("test");
switch (e.type) {
case "blur":
element.style["animation-play-state"] = "paused";
break;
case "focus":
element.style["animation-play-state"] = "running";
break;
}
}
$(this).data("prevType", e.type);
})
Ответ 3
Вам не нужно использовать какие-либо классы или переключать их для получения ожидаемого результата. Здесь загрузите этот gist- файл gist и попытайтесь в конце, давайте посмотрим, работает ли это.
Вам нужно установить состояние animation-play-state
при написании CSS, чтобы test
div paused
.
После того, как окно нагрузки, установите animation-play-state
для running
затем установите их снова в соответствии с blur
и focus
события.
Также я заметил, что использование префикса браузера (-webkit-animation-play-state)
помогло мне получить ожидаемый результат, поэтому обязательно используйте их. Я тестировал на firefox и chrome, отлично работает для меня.
Примечание. Это может не работать в этом фрагменте кода здесь (поскольку фрагмент не находится в главном окне этой текущей вкладки). Загрузите ссылку gist, указанную выше, и проверьте в конце.
window.onload = function() {
// not mentioning the state at all does not provide the expected result, so you need to set
// the state to paused and set it to running on window load
document.getElementById('test').style.webkitAnimationPlayState = "running";
document.getElementById('test').style.animationPlayState = 'running';
}
window.onblur = function() {
document.title = 'paused now';
document.getElementById('test').style.webkitAnimationPlayState = "paused";
document.getElementById('test').style.animationPlayState = 'paused';
document.getElementById('test').style.background = 'pink'; // for testing
}
window.onfocus = function() {
document.title = 'running now';
document.getElementById('test').style.webkitAnimationPlayState = "running";
document.getElementById('test').style.animationPlayState = 'running';
document.getElementById('test').style.background = 'red'; // for testing
}
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;
/* add the state here and set it to running on window load */
-webkit-animation-play-state: paused;
animation-play-state: paused;
}
@keyframes move {
to {
left: 90vw
}
}
<div id="test"></div>