Files
IDE-Demo-B/js/index-carrousel.js
2026-10-08 10:04:29 -03:00

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();
})();