Una pequeña animación en un sitio puede agregar un poco de sensación, impresionar a los usuarios y captar su atención. Puede hacer que comiencen, sin importar dónde se encuentren en la página, tan pronto como se cargue la página. Pero, ¿qué sucede si su sitio web es bastante largo, por lo que el usuario tardó un tiempo en desplazarse hacia abajo hasta ese elemento? Él puede perdérselo.
Puede hacer que se ejecuten todo el tiempo, pero tal vez la animación esté mejor diseñada para asegurarse de que pueda ver el comienzo, por así decirlo.
Para hacer frente a esto, utilizamos disparadores de desplazamiento. Cuando el usuario se desplaza hacia abajo a un elemento en particular, podemos usar ese evento para hacer algo. Puede ser cualquier cosa, incluso el comienzo de la animación. Incluso se puede activar desplazando la carga diferida de imágenes o la carga diferida de una sección completa de comentarios. De esta forma, no obligaremos a los usuarios a descargar elementos que no están en la ventana gráfica cuando cargan la página por primera vez. Es posible que muchos usuarios no se desplacen hacia abajo en absoluto, por lo que realmente les ahorramos (y a nosotros) ancho de banda y tiempo de carga.
Los activadores de desplazamiento son muy útiles. Hay muchas bibliotecas que puede usar para aplicarlos, p. El popular complemento ScrollTrigger de Greensockpero tu no tener use una biblioteca de terceros, especialmente para ideas relativamente simples. De hecho, puede aplicarlo usted mismo usando solo un pequeño puñado de JavaScript estándar. Esto es lo que haremos en este artículo.
Aquí le mostramos cómo hacer que suceda nuestro evento de desplazamiento
- Crea una característica llamada
scrollTriggerpodemos aplicar a ciertos elementos - Adjunte un
.activeclase en un elemento cuando ingresa a la ventana gráfica - Anima esto.
activeclase con CSS
Hay ocasiones en las que se añade un .active la clase no es suficiente. Por ejemplo, podríamos querer realizar una función personalizada en su lugar. Esto significa que debemos poder transmitir una función personalizada que se ejecute cuando el elemento esté visible. Por lo tanto:
scrollTrigger('.loader', {
cb: function(el) {
el.innerText="Loading ..."
loadContent()
}
})
También intentaremos procesar activadores de desplazamiento para navegadores antiguos no compatibles.
Pero primero, en IntersectionObserver API
La función principal de JavaScript que usaremos es Intersection Observer. Esta API proporciona una forma de asincrónicamente monitorea los cambios en la intersección del elemento objetivo, y lo hace de una manera más efectiva que monitorear scroll eventos. Usaremos IntersectionObserver para monitorear cuando el desplazamiento alcanza el punto donde ciertos elementos son visibles en la página.
Comencemos a construir el disparador de desplazamiento
Queremos crear una función llamada scrollTrigger y esta función debe aceptar un selector como argumento.
function scrollTrigger(selector) {
// Multiple element can have same class/selector,
// so we are using querySelectorAll
let els = document.querySelectorAll(selector)
// The above `querySelectorAll` returns a nodeList,
// so we are converting it to an array
els = Array.from(els)
// Now we are iterating over the elements array
els.forEach(el => {
// `addObserver function` will attach the IntersectionObserver to the element
// We will create this function next
addObserver(el)
})
}
// Example usage
scrollTrigger('.scroll-reveal')
Ahora vamos a crear addObserver función que desea adjuntar al elemento mediante IntersectionObserver:
function scrollTrigger(selector){
let els = document.querySelectorAll(selector)
els = Array.from(els)
els.forEach(el => {
addObserver(el)
})
}
function addObserver(el){
// We are creating a new IntersectionObserver instance
let observer = new IntersectionObserver((entries, observer) => { // This takes a callback function that receives two arguments: the elements list and the observer instance.
entries.forEach(entry => {
// `entry.isIntersecting` will be true if the element is visible
if(entry.isIntersecting) {
entry.target.classList.add('active')
// We are removing the observer from the element after adding the active class
observer.unobserve(entry.target)
}
})
})
// Adding the observer to the element
observer.observe(el)
}
// Example usage
scrollTrigger('.scroll-reveal')
Si hacemos esto y nos desplazamos a un elemento con un .scroll-reveal clase, un .active La clase se agrega a este elemento. Pero fíjate que active La clase se agrega tan pronto como cada pequeña parte del elemento es visible.

Pero esto puede ser innecesario. Es posible que queramos en su lugar .active clase que se añadirá una vez al mayor parte del elemento es visible. Bueno, afortunadamente, IntersectionObserver acepta algunas opciones para esto como segundo argumento. Apliquémoslos a los nuestros. scrollTrigger función:
// Receiving options as an object
// If the user doesn't pass any options, the default will be `{}`
function scrollTrigger(selector, options = {}) {
let els = document.querySelectorAll(selector)
els = Array.from(els)
els.forEach(el => {
// Passing the options object to the addObserver function
addObserver(el, options)
})
}
// Receiving options passed from the scrollTrigger function
function addObserver(el, options) {
let observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if(entry.isIntersecting) {
entry.target.classList.add('active')
observer.unobserve(entry.target)
}
})
}, options) // Passing the options object to the observer
observer.observe(el)
}
// Example usage 1:
// scrollTrigger('.scroll-reveal')
// Example usage 2:
scrollTrigger('.scroll-reveal', {
rootMargin: '-200px'
})

¡Y así es, nuestros dos primeros puntos de la agenda se han cumplido!
Pasemos al tercer elemento: agregar la capacidad de realizar una función de devolución de llamada al desplazarse a un elemento de destino. En particular, pasemos la función de devolución de llamada a nuestro sitio con opciones como cb:
function scrollTrigger(selector, options = {}) {
let els = document.querySelectorAll(selector)
els = Array.from(els)
els.forEach(el => {
addObserver(el, options)
})
}
function addObserver(el, options){
let observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if(entry.isIntersecting){
if(options.cb) {
// If we've passed a callback function, we'll call it
options.cb(el)
} else{
// If we haven't, we'll just add the active class
entry.target.classList.add('active')
}
observer.unobserve(entry.target)
}
})
}, options)
observer.observe(el)
}
// Example usage:
scrollTrigger('.loader', {
rootMargin: '-200px',
cb: function(el){
el.innerText="Loading..."
// Done loading
setTimeout(() => {
el.innerText="Task Complete!"
}, 1000)
}
})

¡Estupendo! Hay una última cosa de la que debemos ocuparnos: la compatibilidad con navegadores heredados. Algunos navegadores pueden no ser compatibles con IntersectionObserverentonces tratemos este caso en el nuestro addObserver función:
function scrollTrigger(selector, options = {}) {
let els = document.querySelectorAll(selector)
els = Array.from(els)
els.forEach(el => {
addObserver(el, options)
})
}
function addObserver(el, options) {
// Check if `IntersectionObserver` is supported
if(!('IntersectionObserver' in window)) {
// Simple fallback
// The animation/callback will be called immediately so
// the scroll animation doesn't happen on unsupported browsers
if(options.cb){
options.cb(el)
} else{
entry.target.classList.add('active')
}
// We don't need to execute the rest of the code
return
}
let observer = new IntersectionObserver((entries, observer) =>; {
entries.forEach(entry => {
if(entry.isIntersecting) {
if(options.cb) {
options.cb(el)
} else{
entry.target.classList.add('active')
}
observer.unobserve(entry.target)
}
})
}, options)
observer.observe(el)
}
// Example usages:
scrollTrigger('.intro-text')
scrollTrigger('.scroll-reveal', {
rootMargin: '-200px',
})
scrollTrigger('.loader', {
rootMargin: '-200px',
cb: function(el){
el.innerText="Loading..."
setTimeout(() => {
el.innerText="Task Complete!"
}, 1000)
}
})
Aquí está esta demostración en vivo de nuevo:
¡Y eso es todo por este pequeño viaje! Espero que lo hayan disfrutado y aprendido algo nuevo en el proceso.
