Событие прокрутки не запускается в Chrome, если document.hidden имеет значение true. Есть обходные пути?
Событие прокрутки никогда не запускается Chrome, когда страница скрыта, несмотря на то, что страница фактически прокручивается. Это похоже на то, что они реализовали, чтобы уменьшить использование процессора и сети для невидимых страниц.
Есть ли способ обойти это поведение, даже используя флаги или расширения Chrome? Мне нужно, чтобы событие "прокрутки" запускалось, потому что это то, что я тестирую.
setInterval(() => {
window.scrollBy(0, 100);
// scrolls indefinitely even when the page is hidden
}, 1000);
addEventListener("scroll", () => {
console.log("scroll " + document.documentElement.scrollTop);
// however, this gets fired only if document.hidden is false
});
1 ответ
Это действительно в соответствии со спецификациями.
Событие прокрутки должно запускаться как часть обновления шагов рендеринга цикла событий. Это обновление рендеринга может быть сокращено на этапах 2–5, когда браузер может отказаться от него, если сочтет рендеринг бесполезным (например, когда документ скрыт).
Таким образом, несмотря на то, что прокрутка действительно произошла, поскольку рендеринг еще не произошел, событие, которое нужно запускать, отсутствует.
Примечание. В Firefox добавление вызова к
requestAnimationFrame
заставят событие срабатывать на несколько секунд, но быстро они покажут поведение Chrome по ограничению всех вызовов rAF, пока документ снова не станет видимым.
Чтобы решить эту проблему, это зависит от конкретной ситуации.
Если вы контролируете, откуда появился свиток, как в вашем примере, то запустить его самостоятельно довольно просто, для этого даже не требуется событие.
setInterval(() => {
window.scrollBy(0, 100);
console.log("scroll " + document.documentElement.scrollTop);
}, 1000);
:root { height: 100000vh }
Если вы не несете ответственности за оригинал
setInterval
, но зная его частоту, вы также можете запустить свой собственный интервал параллельно:
setInterval(() => {
window.scrollBy(0, 100);
}, 1000);
setInterval(() => {
console.log("scroll " + document.documentElement.scrollTop);
}, 1000);
:root { height: 100000vh }
Если вы не уверены, как он запускается, вы можете пойти дальше и перезаписать все методы прокрутки и сеттеры, чтобы они также выполняли ваш обратный вызов.
{
// here we overwrite only scrollBy
const orig = window.scrollBy;
window.scrollBy = function(...args) {
orig.call(this, ...args);
console.log("scroll " + document.documentElement.scrollTop);
};
}
setInterval(() => {
window.scrollBy(0, 100);
}, 1000);
:root { height: 100000vh }
И если вам все еще нужно выяснить, произошла ли прокрутка пользователя, вы можете смягчить все эти обходные пути, вызвав обратный вызов только тогда, когда
document.hidden
верно, и пусть
scroll
обработчик событий остальные.
PS: Если вы беспокоитесь о гладкой прокрутке, заметьте, что браузеры не обновлять сглаженное положение прокрутки, когда документ скрыт.