Ahora se muestra IntersectionObserver

IntersectionObservers te informan cuando un elemento observado entra o sale del viewport del navegador.

Navegadores compatibles

  • 51
  • 15
  • 55
  • 12.1

Origen

Supongamos que deseas realizar un seguimiento cuando un elemento de tu DOM ingresa a la vista del puerto visible. Te recomendamos hacerlo para poder cargar imágenes de forma diferida justo a tiempo o porque necesitas saber si el usuario realmente está viendo un determinado banner de anuncio. Para ello, conecta el evento de desplazamiento o usa un temporizador periódico y llama a getBoundingClientRect(). sobre ese elemento.

Sin embargo, este enfoque es extremadamente lento, ya que cada llamada a getBoundingClientRect() fuerza al navegador a cambiar el diseño de toda la página y provoca un bloqueo considerable en tu sitio web. Los asuntos se vuelven casi imposibles cuando sabes que tu sitio se está cargando dentro de un iframe y quieres saber cuándo el usuario puede ver un elemento. El modelo de origen único y el navegador no te permitirán acceder a ningún dato de la página web que contenga el iframe. Este es un problema habitual para los anuncios, por ejemplo, que se cargan frecuentemente mediante iframes.

Esta prueba de visibilidad es más eficiente. IntersectionObserver Se diseñó para y está disponible en todos los navegadores modernos. IntersectionObserver te permite saber cuándo un elemento observado entra o sale del viewport del navegador.

Visibilidad de iframe

Cómo crear un IntersectionObserver

La API es bastante pequeña y se describe mejor con un ejemplo:

const io = new IntersectionObserver(entries => {
  console.log(entries);
}, {
  /* Using default options. Details below */
});

// Start observing an element
io.observe(element);

// Stop observing an element
// io.unobserve(element);

// Disable entire IntersectionObserver
// io.disconnect();

Con las opciones predeterminadas para IntersectionObserver, se llamará a tu devolución de llamada cuando el elemento aparezca parcialmente y cuando salga por completo del viewport.

Si necesitas observar varios elementos, es posible y se recomienda observar varios con la misma instancia de IntersectionObserver llamando a observe() varias veces.

Se pasa un parámetro entries a tu devolución de llamada, que es un array de objetos IntersectionObserverEntry. Cada uno de esos objetos contiene datos de intersección actualizados para uno de los elementos observados.

🔽[IntersectionObserverEntry]
    time: 3893.92
    🔽rootBounds: ClientRect
        bottom: 920
        height: 1024
        left: 0
        right: 1024
        top: 0
        width: 920
    🔽boundingClientRect: ClientRect
    // ...
    🔽intersectionRect: ClientRect
    // ...
    intersectionRatio: 0.54
    🔽target: div#observee
    // ...

rootBounds es el resultado de llamar a getBoundingClientRect() en el elemento raíz, que es el viewport de forma predeterminada. boundingClientRect es el resultado de getBoundingClientRect() llamado en el elemento observado. intersectionRect es la intersección de estos dos rectángulos y te indica de manera efectiva qué parte del elemento observado es visible. intersectionRatio está estrechamente relacionado y te indica qué porcentaje del elemento es visible. Con esta información a tu disposición, ahora puedes implementar funciones como la carga justo a tiempo de los recursos antes de que sean visibles en la pantalla. de forma eficiente.

Proporción de intersección.

Los IntersectionObserver entregan sus datos de forma asíncrona, y tu código de devolución de llamada se ejecutará en el subproceso principal. Además, la especificación en realidad indica que las implementaciones de IntersectionObserver deben usar requestIdleCallback(). Esto significa que la llamada a la devolución de llamada proporcionada tiene baja prioridad y la realizará el navegador durante el tiempo de inactividad. Esta es una decisión de diseño consciente.

Elementos div de desplazamiento

No me gusta mucho desplazarme dentro de un elemento, pero no estoy aquí para juzgar, y tampoco lo es IntersectionObserver. El objeto options toma una opción root que te permite definir una alternativa al viewport como raíz. Es importante tener en cuenta que root debe ser un elemento principal de todos los elementos observados.

¡Combina todas las cosas!

¡No! ¡Qué mal desarrollador! Eso no tiene en cuenta el uso consciente de los ciclos de CPU del usuario. Pensemos en un desplazador infinito como ejemplo. En ese caso, definitivamente es recomendable agregar centinelas al DOM y observarlos (y reciclarlos). Deberías agregar un centinela cerca del último elemento del desplazamiento infinito. Cuando aparece ese sentinela, puedes usar la devolución de llamada para cargar datos, crear los siguientes elementos, adjuntarlos al DOM y reposicionar el sentinela según corresponda. Si reciclas correctamente el centinela, no se necesita ninguna llamada adicional a observe(). IntersectionObserver sigue funcionando.

Desplazamiento infinito

Hay más actualizaciones,

Como se mencionó anteriormente, la devolución de llamada se activará una sola vez cuando el elemento observado aparezca parcialmente y otra vez cuando salga del viewport. De esta manera, IntersectionObserver te dará una respuesta a la pregunta: "¿El elemento X está a la vista?". Sin embargo, en algunos casos de uso, eso podría no ser suficiente.

Aquí es donde entra en juego la opción threshold. Te permite definir un array de umbrales de intersectionRatio. Se llamará a tu devolución de llamada cada vez que intersectionRatio cruce uno de estos valores. El valor predeterminado para threshold es [0], lo que explica el comportamiento predeterminado. Si cambiamos threshold a [0, 0.25, 0.5, 0.75, 1], recibiremos una notificación cada vez que se muestre un cuarto adicional del elemento:

Animación del umbral.

¿Alguna otra opción?

Por el momento, solo existe una opción adicional para las que se mencionaron anteriormente. rootMargin te permite especificar los márgenes para la raíz, lo que te permite aumentar o reducir el área que se usa en las intersecciones. Estos márgenes se especifican con una cadena de estilo CSS, á la "10px 20px 30px 40px", que especifica los márgenes superior, derecho, inferior y izquierdo, respectivamente. En resumen, el struct de opciones IntersectionObserver ofrece las siguientes opciones:

new IntersectionObserver(entries => {/* … */}, {
  // The root to use for intersection.
  // If not provided, use the top-level document's viewport.
  root: null,
  // Same as margin, can be 1, 2, 3 or 4 components, possibly negative lengths.
  // If an explicit root element is specified, components may be percentages of the
  // root element size.  If no explicit root element is specified, using a
  // percentage is an error.
  rootMargin: "0px",
  // Threshold(s) at which to trigger callback, specified as a ratio, or list of
  // ratios, of (visible area / total area) of the observed element (hence all
  // entries must be in the range [0, 1]).  Callback will be invoked when the
  // visible ratio of the observed element crosses a threshold in the list.
  threshold: [0],
});

Comando mágico de <iframe>

Los elementos IntersectionObserver se diseñaron específicamente para tener en cuenta servicios de anuncios y widgets de redes sociales, que suelen usar elementos <iframe> y podrían beneficiarse de saber si están a la vista. Si una <iframe> observa uno de sus elementos, tanto el desplazamiento de <iframe> como de la ventana que contiene el <iframe> activarán la devolución de llamada en los momentos adecuados. Sin embargo, en este último caso, rootBounds se configurará como null para evitar filtrar datos entre los orígenes.

¿Qué no trata IntersectionObserver?

Algo para tener en cuenta es que IntersectionObserver no es de manera intencional ni perfecta para píxeles ni una latencia baja. Usarlos para implementar iniciativas como las animaciones que dependen del desplazamiento seguramente fallarán, ya que los datos, en sentido estricto, estarán desactualizados para el momento en que los uses. En la explicación, encontrarás más detalles sobre los casos de uso originales de IntersectionObserver.

¿Cuánto trabajo puedo hacer en la devolución de llamada?

Breve y rápido: Si pasas demasiado tiempo en la devolución de llamada, tu app se retrasará. Se aplican todas las prácticas habituales.

Progresa y cruza tus elementos

La compatibilidad del navegador con IntersectionObserver es buena, ya que está disponible en todos los navegadores modernos. Si es necesario, se puede usar un polyfill en navegadores más antiguos y está disponible en el repositorio de WICG. Por supuesto, si usas ese polyfill no obtendrás los beneficios de rendimiento que te proporcionaría una implementación nativa.

Puedes comenzar a usar IntersectionObserver ahora mismo. Dinos qué se te ocurrió.