/* ==================================================
01. ESTADO SEGURO PREDETERMINADO
Antes de que JavaScript confirme que todo funciona,
el índice y el CXF permanecen visibles.
De esta manera, si JavaScript falla, ninguno queda
oculto permanentemente.
================================================== */
#po-guia {
opacity: 1;
visibility: visible;
pointer-events: auto;
translate: 0 0;
}
#po-corte-fachada {
opacity: 1;
visibility: visible;
pointer-events: none;
translate: 0 0;
}
/* ==================================================
02. ESTADO INICIAL CONTROLADO POR JAVASCRIPT
JavaScript agrega la clase po-sistema-listo
únicamente después de comprobar que existen
todos los elementos indispensables.
================================================== */
#po-hero.po-sistema-listo #po-guia {
opacity: 0;
visibility: hidden;
pointer-events: none;
translate: -42px 0;
transition:
opacity 450ms ease,
translate 500ms cubic-bezier(0.22, 1, 0.36, 1),
visibility 0s linear 500ms;
}
#po-hero.po-sistema-listo #po-corte-fachada {
opacity: 0;
visibility: hidden;
pointer-events: none;
translate: -110px 0;
transition:
opacity 560ms ease 50ms,
translate 720ms cubic-bezier(0.22, 1, 0.36, 1) 50ms,
visibility 0s linear 770ms;
}
/* ==================================================
03. APERTURA DEL ÍNDICE
Conserva el nombre de clase po-abierto usado
en las versiones anteriores.
================================================== */
#po-hero.po-sistema-listo #po-guia.po-abierto {
opacity: 1;
visibility: visible;
pointer-events: auto;
translate: 0 0;
transition:
opacity 450ms ease,
translate 500ms cubic-bezier(0.22, 1, 0.36, 1),
visibility 0s linear 0s;
}
/* ==================================================
04. APARICIÓN LATERAL DEL CXF
Entra junto con el índice, con un retraso pequeño
para producir una ligera profundidad.
================================================== */
#po-hero.po-sistema-listo
#po-corte-fachada.po-cxf-visible {
opacity: 1;
visibility: visible;
pointer-events: none;
translate: 0 0;
transition:
opacity 560ms ease 60ms,
translate 720ms cubic-bezier(0.22, 1, 0.36, 1) 60ms,
visibility 0s linear 0s;
}
/* ==================================================
05. BOTÓN INICIAL: RECORRER EL LUGAR
================================================== */
#po-acceso {
cursor: pointer;
opacity: 1;
visibility: visible;
transition:
opacity 300ms ease,
translate 300ms ease,
visibility 0s linear 0s;
}
#po-acceso.po-oculto {
opacity: 0;
visibility: hidden;
pointer-events: none;
translate: 0 -6px;
transition:
opacity 300ms ease,
translate 300ms ease,
visibility 0s linear 300ms;
}
/* ==================================================
06. PIO DINÁMICO
================================================== */
#po-panel {
position: absolute;
/*
* Distancia horizontal respecto al índice.
* Un valor menor acerca todos los PO.
*/
left: 145px;
opacity: 0;
visibility: hidden;
pointer-events: none;
translate: -12px 0;
transition:
opacity 280ms ease,
translate 280ms ease,
visibility 0s linear 280ms,
top 320ms ease;
}
/* Línea corta de conexión con cada PO */
#po-panel::before {
content: "";
position: absolute;
top: 50%;
right: 100%;
width: 14px;
height: 1px;
background: rgba(255, 255, 255, 0.55);
transform:
translateY(-50%)
scaleX(0);
transform-origin: right center;
transition:
transform 280ms ease;
pointer-events: none;
}
/* Estado visible del PO */
#po-panel.po-visible {
opacity: 1;
visibility: visible;
pointer-events: auto;
translate: 0 0;
transition:
opacity 280ms ease,
translate 280ms ease,
visibility 0s linear 0s,
top 320ms ease;
}
#po-panel.po-visible::before {
transform:
translateY(-50%)
scaleX(1);
}
/* ==================================================
07. NIVELES DEL ÍNDICE
================================================== */
[id^="po-nivel-"] {
cursor: pointer;
transition:
opacity 200ms ease;
}
[id^="po-nivel-"].po-activo {
opacity: 1;
}
[id^="po-nivel-"].po-activo * {
color: #B7D533 !important;
}
/* ==================================================
08. CONTADOR 00 / 08
================================================== */
#po-etiqueta {
color: rgba(255, 255, 255, 0.62);
}
#po-etiqueta .po-numero,
#po-etiqueta .po-total {
color: rgba(255, 255, 255, 0.62);
}
#po-etiqueta .po-diagonal {
color: #B7D533;
opacity: 1;
}
/* ==================================================
09. NOMBRE Y FRASE DE CADA PO
================================================== */
#po-nombre {
color: #FFFFFF !important;
}
#po-frase {
color: rgba(255, 255, 255, 0.78) !important;
}
/* ==================================================
10. ACCESIBILIDAD
================================================== */
@media (prefers-reduced-motion: reduce) {
#po-guia,
#po-acceso,
#po-panel,
#po-panel::before,
#po-corte-fachada {
transition-duration: 1ms !important;
transition-delay: 0ms !important;
}
}
(function () {
function iniciarSistemaPO() {
/* ==============================================
01. ELEMENTOS PRINCIPALES
============================================== */
const hero =
document.getElementById('po-hero');
const indice =
document.getElementById('po-indice');
const acceso =
document.getElementById('po-acceso');
const guia =
document.getElementById('po-guia');
const panel =
document.getElementById('po-panel');
const etiqueta =
document.getElementById('po-etiqueta');
const nombre =
document.getElementById('po-nombre');
const frase =
document.getElementById('po-frase');
const corte =
document.getElementById('po-corte-fachada');
/* ==============================================
02. CONTENIDO DE LOS NUEVE PO
============================================== */
const datos = {
'00': {
nombre: 'VESTÍBULO',
frase:
'Todo comienza cuando alguien imagina una vida distinta.'
},
'01': {
nombre: 'SALA',
frase:
'La arquitectura comienza mucho antes del primer plano.'
},
'02': {
nombre: 'JARDÍN',
frase:
'Materia, tiempo, contexto y habitantes son los componentes de la arquitectura.'
},
'03': {
nombre: 'BIBLIOTECA',
frase:
'La convivencia da forma al habitar y, por lo tanto, a la arquitectura.'
},
'04': {
nombre: 'GALERÍA',
frase:
'Muestra de nuestro enfoque y visión de lo que el habitar debe ser.'
},
'05': {
nombre: 'ESTUDIO',
frase:
'El espacio donde una nueva conversación da inicio.'
},
'06': {
nombre: 'COCINA',
frase:
'Lo que estamos “cocinando” en este momento.'
},
'07': {
nombre: 'COMEDOR',
frase:
'La mesa puesta para nuestros socios, clientes y amigos.'
},
'08': {
nombre: 'MIRADOR',
frase:
'Un vistazo a la ubicación de nuestros proyectos.'
}
};
/* ==============================================
03. VERIFICACIÓN DE ELEMENTOS
Si falta algo, no se agrega po-sistema-listo.
Por lo tanto, índice y CXF permanecen visibles.
============================================== */
if (
!hero ||
!indice ||
!acceso ||
!guia ||
!panel ||
!etiqueta ||
!nombre ||
!frase ||
!corte
) {
console.warn(
'PO: falta uno o más elementos indispensables.'
);
/*
* Limpieza preventiva de clases antiguas.
*/
if (hero) {
hero.classList.remove(
'po-sistema-listo'
);
}
if (guia) {
guia.classList.remove(
'po-abierto'
);
}
if (corte) {
corte.classList.remove(
'po-cxf-preparado',
'po-cxf-animar',
'po-cxf-visible'
);
}
return;
}
/* ==============================================
04. EVITAR EVENTOS DUPLICADOS
============================================== */
if (
indice.dataset.poInicializado === 'true'
) {
return;
}
indice.dataset.poInicializado = 'true';
/* ==============================================
05. LIMPIAR CLASES DE VERSIONES ANTERIORES
============================================== */
hero.classList.remove(
'po-sistema-listo'
);
guia.classList.remove(
'po-abierto'
);
acceso.classList.remove(
'po-oculto'
);
corte.classList.remove(
'po-cxf-preparado',
'po-cxf-animar',
'po-cxf-visible'
);
/*
* Eliminar estilos en línea relacionados con
* pruebas anteriores de animación.
*/
corte.style.removeProperty(
'clip-path'
);
corte.style.removeProperty(
'opacity'
);
corte.style.removeProperty(
'visibility'
);
corte.style.removeProperty(
'translate'
);
/* ==============================================
06. OBTENER LOS NUEVE NIVELES
============================================== */
const niveles =
guia.querySelectorAll(
'[id^="po-nivel-"]'
);
if (!niveles.length) {
console.warn(
'PO: no se encontraron los niveles del índice.'
);
return;
}
let temporizadorSalida;
/* ==============================================
07. LIMPIAR NIVEL ACTIVO
============================================== */
function limpiarActivos() {
niveles.forEach(
function (nivel) {
nivel.classList.remove(
'po-activo'
);
}
);
}
/* ==============================================
08. MOSTRAR EL PO CORRESPONDIENTE
============================================== */
function mostrarPIO(nivel) {
clearTimeout(
temporizadorSalida
);
const numero =
nivel.id.replace(
'po-nivel-',
''
);
const contenido =
datos[numero];
if (!contenido) {
return;
}
/* Contador */
etiqueta.innerHTML =
'' +
numero +
'' +
'' +
' / ' +
'' +
'' +
'08' +
'';
/* Nombre */
nombre.textContent =
contenido.nombre;
/* Frase específica */
frase.textContent =
contenido.frase;
/* ============================================
RECORRIDO VERTICAL EN TODO EL HERO
============================================ */
const heroRect =
hero.getBoundingClientRect();
const indiceRect =
indice.getBoundingClientRect();
const altoPanel =
panel.offsetHeight || 135;
/*
* Márgenes superior e inferior del recorrido.
*/
const margenSuperior = 24;
const margenInferior = 24;
/*
* Niv. 08 queda arriba.
* Niv. 00 queda abajo.
*/
const numeroNivel =
parseInt(numero, 10);
const progreso =
(8 - numeroNivel) / 8;
/*
* Recorrido disponible.
*/
const recorridoDisponible =
Math.max(
0,
heroRect.height -
margenSuperior -
margenInferior -
altoPanel
);
/*
* Posición respecto al Hero.
*/
const posicionRespectoHero =
margenSuperior +
progreso * recorridoDisponible;
/*
* Conversión a coordenadas de FB PO Índice.
*/
const posicionPanel =
heroRect.top -
indiceRect.top +
posicionRespectoHero;
panel.style.top =
posicionPanel + 'px';
/* Activar y mostrar */
limpiarActivos();
nivel.classList.add(
'po-activo'
);
panel.classList.add(
'po-visible'
);
}
/* ==============================================
09. OCULTAR EL PO
============================================== */
function ocultarPIO() {
temporizadorSalida =
setTimeout(
function () {
panel.classList.remove(
'po-visible'
);
limpiarActivos();
},
180
);
}
/* ==============================================
10. INTERACCIONES DE LOS NIVELES
============================================== */
niveles.forEach(
function (nivel) {
nivel.addEventListener(
'mouseenter',
function () {
mostrarPIO(nivel);
}
);
nivel.addEventListener(
'mouseleave',
ocultarPIO
);
nivel.addEventListener(
'click',
function (evento) {
evento.preventDefault();
mostrarPIO(nivel);
}
);
nivel.addEventListener(
'focusin',
function () {
mostrarPIO(nivel);
}
);
}
);
/* ==============================================
11. MANTENER VISIBLE AL PASAR SOBRE EL PO
============================================== */
panel.addEventListener(
'mouseenter',
function () {
clearTimeout(
temporizadorSalida
);
}
);
panel.addEventListener(
'mouseleave',
ocultarPIO
);
/* ==============================================
12. ABRIR ÍNDICE Y CXF SIMULTÁNEAMENTE
============================================== */
acceso.addEventListener(
'click',
function (evento) {
evento.preventDefault();
/*
* Entrada lateral del índice.
*/
guia.classList.add(
'po-abierto'
);
/*
* Entrada lateral del CXF.
*/
corte.classList.add(
'po-cxf-visible'
);
/*
* Desaparición del botón.
*/
acceso.classList.add(
'po-oculto'
);
}
);
/* ==============================================
13. ACTIVAR EL ESTADO INICIAL OCULTO
Solo se hace después de:
- comprobar todos los elementos;
- encontrar los niveles;
- registrar las interacciones;
- registrar el clic del botón.
============================================== */
window.requestAnimationFrame(
function () {
window.requestAnimationFrame(
function () {
hero.classList.add(
'po-sistema-listo'
);
}
);
}
);
}
/* ==============================================
14. INICIAR EL SISTEMA
============================================== */
if (
document.readyState === 'loading'
) {
document.addEventListener(
'DOMContentLoaded',
iniciarSistemaPO
);
} else {
iniciarSistemaPO();
}
})();