En el ejemplo de código a continuación, hay un botón para desplazarse hasta la parte inferior de la página, pasando por seis divs observados.
isIntersecting dispara para cada elemento a medida que pasan a través de la ventana gráfica. ¿Es posible acelerar o agregar un retraso al disparador para evitar el evento de intersección para elementos que solo están brevemente en la ventana gráfica?
Idealmente, en el siguiente ejemplo, el contador de interacción sería 2 después de hacer clic en el botón de desplazamiento hacia abajo: una detección para el primer elemento y otra para el último elemento, ignorando los que están en el medio.
const blocks = document.querySelectorAll('.block'); const counter = document.querySelector('.counter'); const observer = new IntersectionObserver(callback, { threshold: 0.5 }); let count = 0; blocks.forEach(block => observer.observe(block)); function scrollDown(y = document.body.clientHeight) { window.scrollTo({ top: y, behavior: 'smooth' }); } function callback(entries) { entries.forEach(entry => { if (entry.isIntersecting) { count++; counter.innerText = `Intersections: ${count}`; entry.target.style.backgroundColor = 'lightblue'; } else { entry.target.style.backgroundColor = 'lightpink'; } }); }; .block { width: 50vw; height: 80vh; margin: 20px auto; } .counter { position: fixed; top: 50px; left: 20px; } <p class="counter"></p> <button onclick="scrollDown();">Scroll To Bottom</button> <div class="block"></div> <div class="block"></div> <div class="block"></div> <div class="block"></div> <div class="block"></div> <div class="block"></div> <button onclick="scrollDown(0);">Scroll To Top</button>Aquí hay un enfoque:
cada vez que se encuentre un elemento de intersección, incremente el count y realice el manejo necesario en la devolución de llamada setTimeout configurada para ejecutarse después 500 milisegundos (este número se puede cambiar de acuerdo con la velocidad de desplazamiento)
almacenar el número devuelto por setTimeout en una variable
al configurar setTimeout , verifique si la variable contiene un valor. Si es así, use clearTimeout para eliminar ese setTimeout , por lo que cualquier código que programó para ejecutar no se ejecutará.
una vez que haya dejado de desplazarse, se ejecutará el código en la devolución de llamada de setTimeout , y solo se manejará el último elemento desplazado (ya que se borraron los setTimeout anteriores para manejar los otros elementos).
const blocks = document.querySelectorAll('.block'); const counter = document.querySelector('.counter'); const observer = new IntersectionObserver(callback); let count = 0; blocks.forEach(block => observer.observe(block)); function scrollDown(y = document.body.clientHeight) { window.scrollTo({ top: y, behavior: 'smooth' }); } var lastTimeout; function callback(entries) { entries.forEach(entry => { if (entry.isIntersecting) { if (lastTimeout) clearTimeout(lastTimeout) lastTimeout = setTimeout(function() { count++; counter.innerText = `Intersections: ${count}`; entry.target.style.backgroundColor = 'lightblue'; }, 500); } else { entry.target.style.backgroundColor = 'lightpink'; } }); }; .block { width: 50vw; height: 80vh; margin: 20px auto; } .counter { position: fixed; top: 50px; left: 20px; } <p class="counter"></p> <button onclick="scrollDown();">Scroll To Bottom</button> <div class="block"></div> <div class="block"></div> <div class="block"></div> <div class="block"></div> <div class="block"></div> <div class="block"></div> <button onclick="scrollDown(0);">Scroll To Top</button>