# Componentes Personalizados para Slidev ## ProjectionToggle - Toggle para Modo Proyector ### 📍 Ubicación `slides/components/ProjectionToggle.vue` ### 🎯 Descripción Botón flotante para cambiar entre modo Monitor (oscuro) y modo Proyector (más claro) durante la presentación. ### ✨ Características 1. **Toggle visual**: Botón flotante con iconos 🖥️ / 📽️ 2. **Persistencia**: Guarda la preferencia en localStorage 3. **Feedback visual**: Cambia de color según el modo activo 4. **No invasivo**: Se oculta automáticamente en modo presentador y al imprimir 5. **CSS Variables**: Usa variables CSS para cambios instantáneos ### 📝 Uso Agrégalo a tu primera slide o a todas las slides principales: ```vue ``` O en markdown: ```markdown --- # Primera Slide --- # Tu contenido aquí... ``` ### 🎨 Estados Visuales **Monitor Mode** (por defecto) - Icono: 🖥️ Monitor - Color: Naranja (gradiente Rust) - Fondo: #1c1c1c (muy oscuro) **Projection Mode** - Icono: 📽️ Projection - Color: Verde (#48bb78) - Fondo: #2d3748 (dark pero más visible) ### 💡 ¿Por qué dos modos? Los proyectores tienen menor contraste que los monitores. El modo Projection: - Fondo más claro (#2d3748 vs #1c1c1c) - Mayor contraste de texto - Bordes más gruesos en componentes - Mejor visibilidad en salas con luz ambiente ### 🔧 Cómo Funciona 1. Click en el botón 2. Agrega/quita la clase `projection-mode` al `` 3. Las CSS variables cambian automáticamente: ```css :root { --bg-primary: #1c1c1c; /* Monitor */ } .projection-mode { --bg-primary: #2d3748; /* Projection */ } ``` 4. Guarda la preferencia en `localStorage` ### 📖 Documentación Completa Ver: `slides/PROJECTION_MODE.md` para guía detallada sobre: - Todos los métodos de activación - Comparación visual - Personalización de colores - Troubleshooting ### 🎯 Recomendación de Uso Antes de tu presentación: 1. Agrega `` a la primera slide 2. Durante el soundcheck con el proyector, prueba ambos modos 3. El modo elegido se guardará automáticamente --- ## YearsCounter - Contador Animado de Años ### 📍 Ubicación `slides/components/YearsCounter.vue` ### 🎯 Descripción Componente SVG animado que muestra un contador de años pasando como hojas de calendario, desde 1 hasta el año actual. ### ✨ Características 1. **Animación de contador**: Los números pasan de 1 hasta 40 (en 2025) 2. **Efecto de hoja**: Animación de scale que simula una página de calendario volteándose 3. **Badge animado**: Fondo con gradiente verde y efecto de brillo pulsante 4. **SVG puro**: Más ligero y eficiente que componentes complejos 5. **Totalmente personalizable**: Props para ajustar año inicial y velocidad ### 📝 Uso En cualquier slide de Slidev: ```vue ``` ### 🎛️ Props | Prop | Tipo | Default | Descripción | |------|------|---------|-------------| | `startYear` | Number | 1985 | Año desde el que se cuenta | | `speed` | Number | 80 | Velocidad en milisegundos por año (menor = más rápido) | | `delay` | Number | 3000 | Delay en ms antes de iniciar la animación (después de que la slide sea visible) | ### 🔧 Ejemplos de Configuración #### Más Rápido (50ms por año) ```vue ``` #### Más Lento (150ms por año) ```vue ``` #### Desde otro año (ej: experiencia con Rust) ```vue ``` #### Con delay personalizado (iniciar 5 segundos después) ```vue ``` #### Sin delay (iniciar inmediatamente cuando sea visible) ```vue ``` ### 🎨 Personalización del Estilo El componente usa estas características visuales: 1. **Badge Verde**: - Gradiente: `rgba(72,187,120,0.2)` → `rgba(72,187,120,0.4)` - Borde: `#48bb78` (verde Rust accent) - Bordes redondeados: `15px` 2. **Número**: - Color: `#4ade80` (verde brillante) - Tamaño: `48px` - Fondo oscuro con opacidad 3. **Animaciones**: - **Pulso del badge**: 3 segundos, brillo entre 0.3 y 0.6 opacidad - **Flip del número**: 0.3 segundos, scale de `1,1` → `1,0.3` → `1,1` ### 🖼️ Estructura del SVG ```svg 💻 años como desarrollador ``` ### 🔄 Cómo Funciona la Animación #### Detección de Visibilidad (Nuevo) 1. **IntersectionObserver**: Monitorea cuando la slide es visible (30% threshold) 2. **Activación única**: Solo se inicia la primera vez que aparece 3. **Delay configurable**: Espera 3 segundos (por defecto) antes de iniciar 4. **Compatible**: Funciona tanto en Slidev como en navegación normal #### Secuencia de la Animación 1. **Slide visible**: IntersectionObserver detecta que el componente es visible 2. **Delay**: Espera el tiempo configurado (por defecto 3000ms) 3. **Inicio**: Comienza el contador desde 1 4. **Incremento**: Cada `speed` milisegundos, incrementa el contador 5. **Efecto flip**: Cada cambio de número aplica una animación de scale en el eje Y 6. **Fin**: Cuando alcanza el año objetivo (2025-1985=40), detiene el intervalo **Ejemplo de timing completo**: - Llegas a la slide 2 → espera 3 segundos → cuenta de 1 a 40 en 3.2 segundos = **6.2 segundos total** ### 💻 Código JavaScript ```javascript const counterElement = ref(null) // Referencia al elemento DOM const displayYear = ref(1) const hasStarted = ref(false) // Prevenir múltiples inicios const targetYear = new Date().getFullYear() - props.startYear // 2025 - 1985 = 40 const startAnimation = () => { if (hasStarted.value) return // Solo iniciar una vez hasStarted.value = true // Esperar el delay configurado antes de iniciar setTimeout(() => { let year = 1 const interval = setInterval(() => { if (year <= targetYear) { displayYear.value = year year++ } else { clearInterval(interval) } }, props.speed) }, props.delay) } onMounted(async () => { await nextTick() // Observar cuando el componente es visible const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting && !hasStarted.value) { startAnimation() observer.disconnect() // Dejar de observar después de iniciar } }) }, { threshold: 0.3 } // 30% visible ) observer.observe(counterElement.value) }) ``` ### 🎬 Resultado Cuando navegas a la slide: 1. **Espera 3 segundos** (delay configurable) 2. **Inicia en 1** 3. **Va incrementando** cada 80ms 4. **Animación de flip** en cada cambio 5. **Termina en 40** (años desde 1985 hasta 2025) **Duración total**: - Delay: 3 segundos - Animación: 40 años × 80ms = 3.2 segundos - **Total: 6.2 segundos** ### ✨ Comportamiento Inteligente - ✅ **Solo se inicia cuando la slide es visible** (no al cargar la presentación) - ✅ **Delay de 3 segundos** para dar tiempo al usuario a leer el título - ✅ **Se inicia solo una vez** (aunque vuelvas a la slide, no se reinicia) - ✅ **Compatible con navegación** hacia adelante y atrás en Slidev ### 📱 Responsive El SVG se adapta automáticamente al contenedor y mantiene su aspecto. ### 🔄 Actualización Automática El cálculo `new Date().getFullYear() - props.startYear` se hace al montar el componente, por lo que: - En **2025**: muestra de 1 a 40 - En **2026**: mostrará de 1 a 41 - Y así sucesivamente ### 🎯 Implementación en el Slide **Slide 2** - Introducción Personal: ```markdown --- layout: intro --- # Jesús Pérez Lorenzo
Rust Developer & Cloud Architect
...
``` ### 🛠️ Modificar la Animación Para cambiar el tipo de animación, edita la sección `` en el componente: ```xml ``` ### 🎨 Cambiar Colores Para cambiar el esquema de colores, modifica: ```xml ``` ## 🚀 Crear Otros Contadores Puedes reutilizar el componente para otras métricas: ```vue ``` ## 📦 Archivos del Componente ``` slides/ ├── components/ │ ├── YearsCounter.vue ← El componente │ └── README.md ← Esta documentación └── slides.md ← Uso del componente ``` ## 🔍 Troubleshooting ### El componente no se muestra - Asegúrate de que el archivo esté en `slides/components/` - Slidev detecta automáticamente componentes en esta carpeta ### La animación es muy rápida/lenta - Ajusta el prop `:speed` (en milisegundos) - Valores recomendados: 50-150ms ### El número no llega al año correcto - Verifica que `startYear` sea correcto - El cálculo es: `new Date().getFullYear() - startYear`