Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Intersection Observer

22/28
Recursos

Aportes 33

Preguntas 8

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Con el IntersectionObserver podemos decirle a JavaScript que observe un objeto cuando está dentro de la pantalla (o cuando sale de esta), en el Curso Profesional de JavaScript se habla sobre esto, específicamente en la clase de Intersection Observer, les dejo el link por si quieren profundizar en ello:
.
https://platzi.com/clases/1642-javascript-profesional/22175-intersectionobserver/
.
También les dejo el link de la documentación de esto:
.
https://developer.mozilla.org/es/docs/Web/API/Intersection_Observer_API
.
Y también dejo el código de esta clase 😄
.
Adición del Intersection Observer

Hice varios experimentos con la API y creo que vale la pena aclarar algunos puntos de la clase:

  1. Cuando se crea el observer de la forma que lo hace el profesor, se define por defecto un umbral = 0 para ejecutar el callback. Es decir, el observer va a validar si la imagen se ve o no se ve (así sea un poquito). Para este ejercicio está perfecto, pero ese umbral es parametrizable si queremos que se ejecute el callback por ejemplo si la imagen se ve en un 50% o más. Para eso hay que pasar un segundo parámetro (un objeto) llamado option: const observer = new IntersectionObserver(callback, option)
  2. Cuando se ejecuta el callback (que el profesor pasa como arrow function), esta función recibe como parámetro un array que aquí llamamos entries. El profesor dice que en ese array van TODOS los target que el observer está vigilando y no es así. Si hacen la prueba en la consola y en ese callback sólo hacen un console.log(entries), van a ver que siempre imprime un array de 1 posición y esa posición obecede solamente al target que desencadenó el callback (es decir, la imagen que ahora es visible o que dejó de ser visible en la pantalla).
  3. Dado esto, cuando el profesor hace un filter y un forEach dentro del callback, realmente está usando estos métodos sobre un array de 1 posición.
  4. Ese array de 1 posición tiene en esa posición un objeto. Este objeto describe el evento que interceptó el observer. Este objeto tiene dos propiedades muy relevantes aquí:
    isIntersecting : que si es false indica que ya no está en el viewport y si es true indica que ya es visible en el viewport (aunque sea un poquitico).
    target: que indica específicamente cuál elemento (cuál imágen) es la que generó la ejecución del callback.
  5. Entonces, ejecutar el filter realmente valida si ese único objeto en el array está o no está en el viewport. Si lo está seguimos…
  6. El forEach accede a ese único objeto (un recorrido bieeen cortico jeje), y con él ejecuta la función que imprime el ‘holis’ en consola. Bien podría haber impreso la imagen que desencadenó el callback si en vez de llamar la función ‘accion’ hiciera entries.filter(isIntersecting).forEach(entry => console.log(entry.target))
  7. Finalmente, uno pensaría que el callback del observer se ejecuta sólo cuando se genera el evento que definimos (que la imagen aparezca en el viewport), pero no. El callback se ejecuta siempre que ejecutemos la función observer.observe(target) para cada target más las veces que ese target desencadene el callback después. En el ejercicio del curso no se nota porque el profesor hace un filter, pero si dentro del callback solamente colocan un console.log('hola'), van a ver que cada vez que agregen una imagen se imprime el saludo, así la foto aún no sea visible en el viewport.

Aqui el aporte de un crack del curso Profesional de Js. Creditos a quien corresponda.

Aquí les comparto un video donde se explica muy bien esta API.

Se realizan varios ejemplos interesantes que pueden ayudar a completar la información de este video

https://youtu.be/CvXHedd3Z7w

Si te da este error Uncaught SyntaxError: Cannot use import statement outside a module debes colorcar

type="module" 

En la etiqueta script

Algo interesante que realiza el profesor es cuando hace el import de registerImage lo hace por medio de una exportación nombrada , lo que quiere decir es que al momento de importarla en cualquier otro módulo, se tiene te importar tal y como ha sido definida

en honor de la organizacion jeje

Una vez creado el observador recibe una función callback (esta se ejecuta cuando los objetos a observar cumplen con las condiciones establecidas) y opciones que configuran el comportamiento de este.

**- root: ** El elemento que es usado como viewport para comprobar la visibilidad de elemento target. Este debe ser el padre del target a observar, por defecto en la configuración el root será el body o navegador.

- rootMargin: Margen alrededor del elemento root. Este es configurado tal como la propiedad en css (top, right, bottom, left). Nos ayuda a que la función callback se ejecute tomando en cuenta los pixeles del margen.

- threshold: Recibe un array de valores del 0 al 1, estos representan el porcentaje de visibilidad, si queremos que la función callback se ejecute justo cuando el objeto es visible debemos usar 0, si quisiéramos que el callback se ejecute cuando tengamos un 50% de visibilidad usamos 0.5.

let options = {
  root: document.querySelector('#scrollArea'),
  rootMargin: '0px',
  threshold: 1.0
}

let observer = new IntersectionObserver(callback, options);

Fuente: https://developer.mozilla.org/es/docs/Web/API/Intersection_Observer_API#cómo_se_calcula_la_intersección

La dislexia es interesting 👀

Gracias dislexia!! JAJAJA

El intersection Observer se va a encargar de obeservar un elemento
indicado para realizar una acción cuando este sea visible. Para usarlo debemos instaciarlo y después usar sus metodos.

-Recibe como parametro un call back, osea una función que va a ser llamada por el intersectionObeserver.

  • .Observe recibe como parametro el elemento que se va a observar y como función inversa tiene .unObserve que recibe como parametro el elemento que se va a dejar de observar.

**Ejemplos de uso: **

-Como en el curso profesional de JS cuando un video ya no es visible para el usuario pausarlo.

  • Cuando tenemos un carousel automatico pausarlo cuando el usuario no lo este viendo.
  • Realizar una acción cuando el usuario pase un elemento X, como mostrar un modal o Alert
    -Por supuesto el ejemplo de este curso (Hacer Lazy loading), pero no solo con imagenes puede ser con videos, peticiones de datos, e incluso cargar una parte de tu sitio web que consideres que no es principal en tu web, pero incluirla de una en la pagina afectaria la carga de esta arruinando el UX

lazy.js

const isIntersecting = (entry) => {
    return entry.isIntersecting
}

const accion = (entry) => {
    const nodo = entry.target
    console.log('Get it')
    observer.unobserve(nodo)
}

const observer = new IntersectionObserver((entries) => {
    entries.filter(isIntersecting).forEach(accion)
})

export const registerImage = (image) => {
    observer.observe(image);
}

Que buen curso ❤️

Intersection Observer

La API Observador de Intersección provee una vía asíncrona para observar cambios en la intersección de un elemento con un elemento ancestro o con el viewport del documento de nivel superior, aquí están las notas en notion, lo más probable es que en los comentarios no se vea muy bien. 😅

const observer = new IntersectionObserver((entries, observer) => {
	// El primer parámetro es un arreglo con datos de los nodos que se están observando
	// * boundingClientRect: Con las propiedades: top, right, bottom, left, width, height, x & y.
	// * intersectionRatio: Número de 0 a 1, representa cuánto se está intersectando
	// * intersectionRect: Las mismas propiedades que boundingClientRect, pero sólo de lectura.
	// * isIntersecting: Booleano que dice si el nodo está dentro del área del observer
	// * isVisible: Bolleano para el intersectionObserver v2 *Necesita opciones extra para funcionar y no es del todo soportado*
	// * rootBounds: Las mismas propiedades de boundingClientRect pero del observer, sólo lectura
	// * target: El nodo al que se está observando
	// * time: Tiempo en milisegundos que se ha estado observando
	console.log(entries);
	// El segundo parámetro es el observer con las opciones que le daremos: root, rootMargin, threshold.
	console.log(observer); 
}, {
	root: nodo, // Si quieres observar un nodo en específico, por defecto null
	rootMargin: "10px", // Hace el área del observador 10 pixeles más grande para todos los lados (Funciona como en CSS)
	threshold: 1, // Número de 0 a 1 que indica cuánto del elemento debe estar en el observer para ser considerado isIntersecting
	// Opciones requeridas para usar isVisible para v2
  trackVisibility: true, // Para activar la visibilidad
  delay: 100, // mínimo 100
);

Creo que este curso es un complemento perfecto para el curso profesional de javascript. Tremendo curso y gran profesor 🙌.

Dejo el codigo de la clase para quien prefiera copiarlo:


const isIntersecting = (entry)=>{
    return entry.isIntersecting // true si esta dentro de la pantalla
}

const accion = (entry)=>{
    const nodo = entry.target;
    console.log('holis');
    observer.unobserve(nodo);
}

const observer = new IntersectionObserver((entries)=>{
    entries.filter(isIntersecting).forEach(accion);
});

export const registerImage = (image) =>{
    // IntersectactionObservador -> observer(image)
    observer.observe(image);
}

ame esta clase, gracias gracias ❤️

Buenas, en caso de que les salga observer: parameter 1 is not the tipe of ‘Element’, eso es porque aun no ha cargado el nodo en el DOM hasta la intersección. Cuando las imágenes son pequeñas me arroja el error, pero cuando es una imagen grande, corre normal el programa.

Sin embargo, el detalle fue que aparte de hacer el proyecto con typescript, lo hice con promesas. Si se quitan, el programa corre normal

Trabajar con el Intersection Observer

/:::Trabajar con el Intersection Observer:::/

const imagen1 = document.getElementById(‘imagen1’)
/------------------------------------------------/

/*Declarar la funcion con la accion que
se va a realizar la cual puede
recibir 2 parametros (entradas y observador)
*/

const accion = (entrada,watch)=>{

entrada.forEach(element => {
    if(element.isIntersecting){
        imagen1.style.setProperty("width","500px")
        imagen1.style.setProperty("heigth","50px")
    }
});

}

/*Creamos un OBSERVADOR invocando
la instancia IntersectionObserver
esta recibe 2 parametro el
primero es la accion que se va a realizar
cuando ocurra el evento y el segundo
sera un objeto donde se realizaran
algunas configuraciones como:

root: --> Seleccionador global del HTML(Es decir Document)

rootMargin: --> Es un margen que puede hacerse grande
o pequeño dependiendo de lo que le indiquemos
funciona como el padding del CSS

threshold: --> Permite indicar
¿Cuando se ejecuta el codigo?, si el elemento
ya esta totalmente adentro ó a la mitad por ejemplo
1.0 indica que ya esta totalmente adentro

*/

const observador = new IntersectionObserver(accion, {
root:null,
rootMargin:‘0px’,
threshold:1.0,
});

//INVOCAMOS AL OBSERVADOR

observador.observe(imagen1)

/*
EN CONCLUSION!
->Trabajar con el intersectionObserver
consta de solo 4 pasos basicos…

1.- Obtener el nodo referencia que queremos afectar
2.- Crear la accion que queremos hacer con ese nodo
3.- COnfigurar el observador
4.- Invocar el observador
*/

¿Que es el viewport?

Si ya has tocado CSS antes recordaras que hay una unidad de la propiedad width y height que es por ejemplo width:100vw; y height:100vh; esto lo que hace es tomar todo el ancho y alto disponible de la pantalla bueno esto es lo que podemos ver al momento en tiempo real en Js este es nuestro viewport todo el ancho y alto disponible al momento

Me ha parecido super interesante esta clase aunque debo confesar que debo verla varias veces para entre serla por completo....

JAJAJAJ “Gracias a mi dislexia” …

La API intersectionObserver provee una vía asíncrona para observar cambios en la intersección de un elemento con un elemento ancestro o con el viewport del documento de nivel superior.

Realmente tenia conflicto en por que usamos el filter al momento de obtener las intersecciones?, me parecia innecesario, pues incluso sin el me funcionaba. Pero luego hice pruebas de rendimiento y con el filter las imagenes me cargaban mas rapido que cuando solo hacia una validacion si el entry estaba intersectando, supongo que es debido a que el filter me retorna un array con el elemento solo si la interseccion es verdadera, al ser falsa retorna un array vacio y el navegador se ahora hacer otro forEach y no hace nada, lo que resulta mas optimo.

intersection observer: Nos permite saber cuando un elemento se intersecta con el viewport de la ventana activa en el navegador.

Me quedé un rato con está clase. Al comienzo me costó un poco pero el profesor si explicó muy bien.

//4 Intersection Observe

//Aplicar el Lazy loading imgs

const isIntersecting = (entry) => {
    //200px lejos de la pantalla entonces haz algo EG
    return entry.isIntersecting //True(dentro de la pantalla)
}

const accion = (entry) => {
    const nodo = entry.target;
    console.log('holis');

    //Si ya hiciste algo, desregistra la imagen (unlisten)
    observer.unobserve(nodo)
}
const observer = new IntersectionObserver((entries) => {
    entries
        .filter(isIntersecting) //Si está presente en el viewport
        .forEach(accion)
})

//entries tambien puede ser allElements

export const registerImage = (imagen) => {
    //IntersectionObservador -> Observar(imagen)
    observer.observe(imagen);
}
// Exportar el metodo creado en lazy.js
import { registerImage } from './lazy'

// Creación de imágenes
{/* <div class="p-4">
<img
  class="mx-auto"
  width="320"
  src="https://randomfox.ca/images/63.jpg"
  alt=""></div>
</div> */}

// Imágenes aleatorias
const minimum = 1;
const maximum = 122;
const random = () => Math.floor(Math.random() * (maximum - minimum) + minimum);

const createImageNote = () => {
    const container = document.createElement('div');
    container.className = "p-4";

    const imagen = document.createElement('img');
    imagen.class = "mx-auto";
    imagen.width =  "320";
    imagen.src = `https://randomfox.ca/images/${random()}.jpg`;
    
    container.appendChild(imagen);
    
    return container;
}

//2.1 Imágenes aleatorias.
const nuevaImagen = createImageNote();
// Agregar una imágene

const mountNode = document.getElementById('images');

//Agregar boton para que al darle click se genere una imagen
const addButton = document.querySelector('button')

const addImage = () => {
    const newImage = createImageNote();
    mountNode.append(newImage);
    registerImage(newImage);
};

//3 agregar imágenes como acción
addButton.addEventListener('click', addImage);

My Code

const isIntersecting=(entry)=>{
    return entry.isIntersecting; // true (dentro de la pantalla)    
};

const action=(entry)=>{
    const node=entry.target;
    console.log('hola');
    //desregister la imagen (unlisten)
    observer.unobserve(node);
};

const observer= new IntersectionObserver((entries)=>{
    entries.filter(isIntersecting).forEach(action);
});

export const registerImage=(image)=>{
    observer.observe(image);
}; 

Lo he realizado usando Fetch, para el que tenga alguna duda. mi código.

const loadImage = () => {
    fetch('https://randomfox.ca/floof/')
        .then( response => response.json())
        .then( data => {
            const newContent = [];
            // create div
            const div = document.createElement('div');
            div.className = 'p-4';

            // create img
            const img = document.createElement('img');
            img.src = data.image;
            img.className = 'mx-auto';
            img.width = '320';

            div.appendChild(img);
            newContent.push(div);
            app.append(...newContent);
            // Otra manera de hacerlo
            // app.appendChild(div);
            registerImage(div);
        });
}

por si les interesa aqui esta la compatibilidad
https://caniuse.com/?search=intersectionObserver

,

Código de la clase:

const isIntersecting = (entry) => {
    return entry.isIntersecting //true si esta en el rango de la pantalla
}

const accion = (entry) => {
    const nodo = entry.target;
    console.log("Escuchando");

    //desregistrar la imagen(unlisten) 
    observer.unobserve(nodo);
}

//intansear el intersectionObserver
const observer = new IntersectionObserver( (entries) => {
    entries.filter(isIntersecting).forEach(accion);
});

export const registerImage = (imagen) => {
    observer.observe(imagen);
}```