У меня есть куча длительных 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>
Приведенный выше код перемещает красный прямоугольник по горизонтали.Для завершения анимации прямоугольнику требуется 5 секунд.
Проблема: после запуска анимации переключитесь на другую вкладку браузера;через некоторое время (более 5 секунд) переключитесь обратно на первую вкладку.
Ожидаемый результат: прямоугольник продолжает свой путь от точки, где он остановился.
Фактический результат: в большинстве случаев прямоугольник появляется в конечном пункте назначения и останавливается.Иногда это работает как ожидалось. Видео демонстрирует проблему.
Я играл с разными значениями animation-fill-mode
и animation-timing-function
, но результат всегда был одинаковым.Как указано в rv7 , , совместное использование примеров в инструментах JS CodePen, JSFiddle, JSBin и stackoverflow влияет на результаты, поэтому лучше проводить тестирование непосредственно на статической странице на локальном HTTP-сервере (или используя ссылки ниже).
Для удобства я развернул приведенный выше код для Heroku .Приложение представляет собой статический HTTP-сервер nodejs, который работает по бесплатной подписке, поэтому загрузка страницы может занять до 5 минут в первый раз.Результаты тестирования на этой странице:
FAIL Chrome 64.0.3282.167 (официальная сборка) (64-разрядная версия) Linux Debian Stretch (ПК)
FAIL Chrome 70.0.3538.67 (официальная сборка) (64-бит) Windows 10 (ПК)
FAIL Chrome 70.0.3538.77 (официальная сборка) (32-разрядная версия) Windows 7 (ПК)
FAIL Chrome 70.0.3538.77 (официальная сборка) (64-разрядная версия) OSX 10.13.5(Mac mini)
FAIL FF Quantum 60.2.2esr (64-разрядная версия) Linux Debian Stretch (ПК)
OK Safari 11.1.1 (13605.2.8) (Mac mini)
API видимости страницы можно заменить на события типа focus
и blur
, например:
window.addEventListener("focus", function() {
document.querySelector("#test").classList.remove("paused");
});
window.addEventListener("blur", function() {
document.querySelector("#test").classList.add("paused");
});
Однако эта замена не эквивалентна.Если страница содержит IFRAME, взаимодействие с их содержимым вызовет события focus
и blur
в главном окне.Выполнение любого кода переключения вкладок в этом случае не является правильным.В некоторых случаях это все еще может быть вариантом, поэтому я развернул страницу для тестирования здесь .Результаты немного лучше:
FAIL Chrome 64.0.3282.167 (официальная сборка) (64-разрядная версия) Linux Debian Stretch (ПК)
FAIL Chrome 70.0.3538.67 (официальная сборка) (64-бит) Windows 10 (ПК)
FAIL Chrome 70.0.3538.77 (официальная сборка) (32-разрядная версия) Windows 7 (ПК)
FAIL Chrome 70.0.3538.77 (официальная сборка) (64-разрядная версия) OSX 10.13.5(Mac mini)
OK FF Quantum 60.2.2esr (64-разрядная версия) Linux Debian Stretch (ПК)
OK Safari 11.1.1 (13605.2.8) (Mac mini)
Эта версия чаще всего выходит из строя вChrome 64-битный, чем в Chrome 32-битный.В 32-битном Chrome я получил всего 1 ошибку после ~ 20 успешных попыток.Это может быть связано с тем, что 32-разрядная версия Chrome установлена на старом оборудовании.
Вопрос: есть ли способ надежно приостанавливать / возобновлять CSS-анимацию при переключении вкладок