Ir al contenido
(function () {
const CAROUSEL_CLASS = 'carousel-fade-gsap';
const FADE_DURATION = 800;
function waitForDependencies(callback, tries = 0) {
if (
window.gsap &&
window.ScrollTrigger &&
window.elementorFrontend
) {
callback();
return;
}
if (tries < 100) {
setTimeout(function () {
waitForDependencies(callback, tries + 1);
}, 100);
}
}
/*
* Reinicia las animaciones GSAP del slide activo.
*/
function restartGsapInSlide(slide) {
if (!slide || !window.gsap || !window.ScrollTrigger) {
return;
}
const containers = slide.querySelectorAll('.trps-container');
if (!containers.length) {
return;
}
containers.forEach(function (root) {
const title = root.querySelector('.trps-title');
if (!title) {
return;
}
/*
* Buscamos los elementos que el plugin ya convirtió
* en palabras/letras.
*/
const units = root.querySelectorAll(
'.trps-word, .trps-char'
);
if (!units.length) {
return;
}
/*
* Eliminamos cualquier ScrollTrigger anterior
* asociado a este título.
*/
ScrollTrigger.getAll().forEach(function (trigger) {
if (trigger.trigger === root) {
trigger.kill();
}
});
/*
* Leemos nuevamente las configuraciones
* originales del widget.
*/
const stagger =
parseFloat(root.dataset.stagger) || 0.06;
const duration =
parseFloat(root.dataset.duration) || 0.9;
const distance =
parseFloat(root.dataset.distance) || 100;
const ease =
root.dataset.ease || 'power3.out';
/*
* Estado inicial.
*/
gsap.killTweensOf(units);
gsap.set(units, {
yPercent: distance,
opacity: 0
});
/*
* Ejecutamos nuevamente la animación.
*
* IMPORTANTE:
* Aquí NO usamos ScrollTrigger.
*
* El Carousel ya nos está diciendo exactamente
* cuándo el slide está visible.
*/
gsap.to(units, {
yPercent: 0,
opacity: 1,
duration: duration,
ease: ease,
stagger: stagger,
overwrite: 'auto'
});
});
/*
* Actualizamos ScrollTrigger después de que el
* slide ya es visible.
*/
ScrollTrigger.refresh();
}
/*
* Inicializa un Carousel.
*/
function initCarousel(carousel) {
if (carousel.dataset.fadeGsapReady === '1') {
return;
}
const swiperElement = carousel.querySelector('.swiper');
if (!swiperElement) {
return;
}
const swiper = swiperElement.swiper;
if (!swiper) {
return;
}
carousel.dataset.fadeGsapReady = '1';
/*
* Cuando termina el cambio de slide,
* esperamos a que termine nuestro fade CSS.
*/
swiper.on('slideChangeTransitionEnd', function () {
setTimeout(function () {
const activeSlide =
swiper.slides[swiper.activeIndex];
restartGsapInSlide(activeSlide);
}, 50);
});
/*
* Ejecutamos también la animación
* del slide inicial.
*/
setTimeout(function () {
const activeSlide =
swiper.slides[swiper.activeIndex];
restartGsapInSlide(activeSlide);
}, FADE_DURATION + 100);
}
/*
* Busca todos los Carousels de Elementor.
*/
function scanCarousels() {
document
.querySelectorAll('.' + CAROUSEL_CLASS)
.forEach(function (carousel) {
initCarousel(carousel);
});
}
/*
* Elementor puede crear el Carousel después de
* cargar la página, por eso esperamos a que Elementor
* termine de inicializar sus widgets.
*/
waitForDependencies(function () {
if (
window.elementorFrontend &&
window.elementorFrontend.hooks
) {
elementorFrontend.hooks.addAction(
'frontend/element_ready/widget',
function () {
setTimeout(scanCarousels, 300);
}
);
}
/*
* Primera búsqueda.
*/
setTimeout(scanCarousels, 500);
/*
* Segunda búsqueda por si Swiper tarda
* un poco más en inicializarse.
*/
setTimeout(scanCarousels, 1500);
/*
* Último intento.
*/
setTimeout(scanCarousels, 3000);
});
})();