Saber quando algo entra no ecrã: IntersectionObserver
Carregar imagens só quando são precisas, animar uma secção quando ela aparece, marcar no menu o capítulo que está a ser lido: são três funcionalidades diferentes com o mesmo problema por baixo — saber o que está visível.
A forma antiga era ouvir o evento scroll e medir posições. Corria dezenas de vezes por segundo, na mesma thread que desenha a página, e era a origem clássica do scroll aos solavancos.
O IntersectionObserver faz a mesma pergunta ao browser, que já sabe a resposta — e avisa só quando muda.
1. O básico
const observador = new IntersectionObserver((entradas) => {
for (const entrada of entradas) {
if (entrada.isIntersecting) {
entrada.target.classList.add('visivel');
observador.unobserve(entrada.target); // uma vez chega
}
}
});
document.querySelectorAll('.animar').forEach((elemento) => observador.observe(elemento));O unobserve depois do primeiro encontro não é detalhe: sem ele, o callback volta a correr a cada entrada e saída do ecrã.
2. As três opções que interessam
new IntersectionObserver(callback, {
// Começar a tratar 200px antes de entrar no ecrã — é o que dá a sensação
// de que a imagem "já lá estava".
rootMargin: '200px',
// Que fração tem de estar visível para contar. 0 = um pixel basta;
// 1 = tem de estar inteiro; um array avisa em vários pontos.
threshold: 0.5,
// O contentor. Por omissão é a janela; pode ser um div com scroll próprio.
root: document.querySelector('#lista'),
});3. Scroll infinito, em oito linhas
const sentinela = document.querySelector('#fim-da-lista');
const observador = new IntersectionObserver(async ([entrada]) => {
if (!entrada.isIntersecting) return;
observador.unobserve(sentinela);
await carregarPaginaSeguinte();
observador.observe(sentinela);
});
observador.observe(sentinela);4. E para imagens, se calhar nem é preciso
Antes de escrever qualquer observador para carregar imagens, lembre-se que o browser já faz isso sozinho:
<img src="foto.jpg" loading="lazy" width="800" height="600" alt="" />O loading="lazy" resolve o caso comum. O observador fica para quando é preciso fazer outra coisa quando algo aparece — e não apenas carregá-lo.