114 lines
3.1 KiB
JavaScript
114 lines
3.1 KiB
JavaScript
/**
|
|
* ECOSISTEMA - CARRUSEL
|
|
* Auto-play con fade, control por tabs, pausa al interactuar,
|
|
* reanudación al salir completamente del viewport.
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
|
|
const INTERVAL_MS = 5000;
|
|
const FADE_MS = 600; // debe coincidir con --eco-fade-duration
|
|
|
|
const section = document.querySelector('.ecosystem-section');
|
|
if (!section) return;
|
|
|
|
const tabs = Array.from(section.querySelectorAll('.eco-tab'));
|
|
const slides = Array.from(section.querySelectorAll('.eco-slide'));
|
|
|
|
let currentIndex = 0;
|
|
let timer = null;
|
|
let userInteracted = false; // true después de un clic manual
|
|
|
|
// ---------- Utilidades ----------
|
|
function goTo(index) {
|
|
if (index < 0) index = slides.length - 1;
|
|
if (index >= slides.length) index = 0;
|
|
|
|
// Actualizar slides
|
|
slides.forEach((slide, i) => {
|
|
if (i === index) {
|
|
slide.classList.add('is-active');
|
|
slide.removeAttribute('hidden');
|
|
} else {
|
|
slide.classList.remove('is-active');
|
|
// Esperamos la transición para ocultar (accesibilidad + rendimiento)
|
|
setTimeout(() => {
|
|
if (!slide.classList.contains('is-active')) {
|
|
slide.setAttribute('hidden', '');
|
|
}
|
|
}, FADE_MS);
|
|
}
|
|
});
|
|
|
|
// Actualizar tabs
|
|
tabs.forEach((tab, i) => {
|
|
if (i === index) {
|
|
tab.classList.add('is-active');
|
|
tab.setAttribute('aria-selected', 'true');
|
|
// Color activo específico de la capacidad
|
|
tab.style.backgroundColor = tab.dataset.color;
|
|
tab.style.borderColor = tab.dataset.color;
|
|
} else {
|
|
tab.classList.remove('is-active');
|
|
tab.setAttribute('aria-selected', 'false');
|
|
// Reset a color inactivo estándar
|
|
tab.style.backgroundColor = '';
|
|
tab.style.borderColor = '';
|
|
}
|
|
});
|
|
|
|
currentIndex = index;
|
|
}
|
|
|
|
function next() {
|
|
goTo(currentIndex + 1);
|
|
}
|
|
|
|
function startAutoPlay() {
|
|
stopAutoPlay();
|
|
timer = setInterval(next, INTERVAL_MS);
|
|
}
|
|
|
|
function stopAutoPlay() {
|
|
if (timer) {
|
|
clearInterval(timer);
|
|
timer = null;
|
|
}
|
|
}
|
|
|
|
// ---------- Eventos de tabs ----------
|
|
tabs.forEach((tab, i) => {
|
|
tab.addEventListener('click', () => {
|
|
userInteracted = true;
|
|
stopAutoPlay();
|
|
goTo(i);
|
|
});
|
|
});
|
|
|
|
// ---------- IntersectionObserver: reanudar al salir del viewport ----------
|
|
// "Salir completamente" = cuando la sección ya no intersecta en absoluto.
|
|
const observer = new IntersectionObserver(
|
|
(entries) => {
|
|
entries.forEach((entry) => {
|
|
if (!entry.isIntersecting) {
|
|
// Salió completamente del viewport
|
|
userInteracted = false;
|
|
startAutoPlay();
|
|
} else {
|
|
// Entró al viewport: si el usuario interactuó, mantenemos pausa;
|
|
// si no, arrancamos el auto-play.
|
|
if (!userInteracted) {
|
|
startAutoPlay();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
{ threshold: 0 } // se dispara cuando la visibilidad cambia de 0 a >0 o viceversa
|
|
);
|
|
|
|
observer.observe(section);
|
|
|
|
// ---------- Init ----------
|
|
goTo(0);
|
|
startAutoPlay();
|
|
})(); |