Spaces:
Running
Running
| <html lang="es"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Análisis de Herramientas de Desarrollo - Grupo 5</title> | |
| <!-- Carga de Tailwind CSS --> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <!-- Fuente Inter --> | |
| <link rel="preconnect" href="https://fonts.googleapis.com"> | |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet"> | |
| <style> | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| background-color: #1a202c; /* gris oscuro para el fondo */ | |
| } | |
| /* Contenedor principal con relación de aspecto 4:3 */ | |
| #presentation-container { | |
| width: 100%; | |
| max-width: 1024px; /* Un tamaño máximo razonable para 4:3 */ | |
| margin: auto; | |
| aspect-ratio: 4 / 3; | |
| box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5); | |
| } | |
| /* Estilo base de cada slide */ | |
| .slide { | |
| transition: opacity 0.4s ease-in-out; | |
| } | |
| /* Marcador de posición para GIFs */ | |
| .gif-placeholder { | |
| border: 4px dashed #4a5568; /* gris-600 */ | |
| border-radius: 0.75rem; /* rounded-xl */ | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 100%; | |
| height: 100%; | |
| background-color: #2d3748; /* gris-800 */ | |
| } | |
| </style> | |
| </head> | |
| <body class="flex items-center justify-center min-h-screen p-4"> | |
| <!-- Contenedor 4:3 --> | |
| <div id="presentation-container" class="bg-gray-900 text-white rounded-lg overflow-hidden relative"> | |
| <!-- Slide 1: Portada --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex flex-col justify-center items-center text-center bg-gray-800"> | |
| <h1 class="text-6xl font-bold text-cyan-400 mb-6">Análisis Comparativo</h1> | |
| <h2 class="text-4xl font-semibold text-white">Herramientas de Desarrollo y Gestión</h2> | |
| <p class="text-3xl text-gray-400 mt-16">Curso: Testing y calidad de software</p> | |
| <p class="text-3xl text-gray-400 mt-4">Grupo 5</p> | |
| </div> | |
| <!-- Slide 2: Introducción --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6">Introducción</h2> | |
| <ul class="list-disc list-inside text-xl space-y-3 text-gray-300"> | |
| <li>Análisis de herramientas clave del SDLC.</li> | |
| <li>Foco en Clientes de API (Postman) y Gestión Ágil (Jira).</li> | |
| <li>Investigación de alternativas modernas.</li> | |
| <li>Comparativa de filosofía, funcionalidad y costos.</li> | |
| </ul> | |
| </div> | |
| <!-- Placeholder GIF --> | |
| <div class="w-1/2"> | |
| <div class="gif-placeholder aspect-video"> | |
| <span class="text-gray-500 text-2xl font-semibold">Espacio para GIF</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 3: Título Parte I --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-5xl font-bold text-cyan-400">Parte I</h2> | |
| <h3 class="text-4xl text-white mt-4">Clientes de API</h3> | |
| <p class="text-2xl text-gray-400 mt-6">Validación y Pruebas de Interfaces</p> | |
| </div> | |
| <!-- Placeholder GIF --> | |
| <div class="w-1/2"> | |
| <div class="gif-placeholder aspect-video"> | |
| <span class="text-gray-500 text-2xl font-semibold">Espacio para GIF</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 4: Herramienta Central: Postman --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6">Herramienta Central: Postman</h2> | |
| <p class="text-xl text-gray-300 mb-4">Plataforma estándar *de facto* para el ciclo de vida de APIs.</p> | |
| <ul class="list-disc list-inside text-lg text-gray-300 space-y-2"> | |
| <li>Rol: Diseño, prueba, documentación y monitoreo.</li> | |
| <li>Evolución: De cliente REST simple a plataforma integral en la nube.</li> | |
| <li>Modelo: *Cloud-first*, centrado en *workspaces* colaborativos.</li> | |
| </ul> | |
| </div> | |
| <div class="w-1/2 flex justify-center items-center"> | |
| <img src="descarga_e_instalacion_postman.gif" | |
| alt="Instalación de Postman" | |
| class="rounded-xl cursor-pointer shadow-lg transition hover:scale-105 duration-300" | |
| onclick="openModal('descarga_e_instalacion_postman.gif')"> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 5: La Crítica a Postman --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6">La Crítica: "Bloat" y Nube</h2> | |
| <p class="text-xl text-gray-300 mb-4">La evolución de Postman abrió el mercado a alternativas.</p> | |
| <ul class="list-disc list-inside text-lg text-gray-300 space-y-2"> | |
| <li><b>Rendimiento:</b> Percepción de lentitud y alto consumo de recursos (*bloat*).</li> | |
| <li><b>Dependencia:</b> El modelo *cloud-first* obligatorio genera fricción.</li> | |
| <li><b>Privacidad:</b> Preocupaciones sobre dónde residen los datos sensibles (tokens, secretos).</li> | |
| </ul> | |
| </div> | |
| <!-- Placeholder GIF --> | |
| <div class="w-1/2"> | |
| <div class="gif-placeholder aspect-video"> | |
| <span class="text-gray-500 text-2xl font-semibold">Espacio para GIF</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 6: Alternativa: Insomnia --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6">Alternativa: Insomnia</h2> | |
| <p class="text-xl text-gray-300 mb-4">Cliente de API Open-Source (propiedad de Kong) enfocado en diseño.</p> | |
| <ul class="list-disc list-inside text-lg text-gray-300 space-y-2"> | |
| <li>Soporta REST, GraphQL, gRPC.</li> | |
| <li><b>Filosofía Híbrida:</b> Permite "Scratch Pad" 100% local o sincronización opcional (Nube o Git).</li> | |
| <li>Potente para diseño (OpenAPI) y *plugins*.</li> | |
| </ul> | |
| </div> | |
| <!-- Placeholder GIF --> | |
| <div class="w-1/2"> | |
| <div class="gif-placeholder aspect-video"> | |
| <span class="text-gray-500 text-2xl font-semibold">Espacio para GIF</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 7: Alternativa: Yaak --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6">Alternativa: Yaak</h2> | |
| <p class="text-xl text-gray-300 mb-4">Cliente moderno enfocado en velocidad y privacidad (*local-first*).</p> | |
| <ul class="list-disc list-inside text-lg text-gray-300 space-y-2"> | |
| <li><b>Privacidad Total:</b> 100% offline por defecto. Cero telemetría.</li> | |
| <li><b>Nativo de Git:</b> Colaboración asíncrona tratando APIs como código.</li> | |
| <li><b>Rendimiento:</b> Extremadamente rápido y ligero (Nativo Rust/Tauri).</li> | |
| </ul> | |
| </div> | |
| <!-- Placeholder GIF --> | |
| <div class="w-1/2 flex justify-center items-center"> | |
| <img src="descarga_e_instalacion_yaak.gif" | |
| alt="Instalación de Yaak" | |
| class="rounded-xl cursor-pointer shadow-lg transition hover:scale-105 duration-300" | |
| onclick="openModal('descarga_e_instalacion_yaak.gif')"> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 8: Tabla Comparativa API (Full Width) --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex flex-col justify-center hidden opacity-0 bg-gray-800"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6 text-center">Comparativa: Clientes de API</h2> | |
| <table class="w-full text-left text-lg"> | |
| <thead class="bg-gray-700"> | |
| <tr> | |
| <th class="p-3">Característica</th> | |
| <th class="p-3">Postman</th> | |
| <th class="p-3">Insomnia</th> | |
| <th class="p-3">Yaak</th> | |
| </tr> | |
| </thead> | |
| <tbody class="text-gray-300"> | |
| <tr class="bg-gray-800 border-b border-gray-700"> | |
| <td class="p-3 font-semibold">Filosofía</td> | |
| <td class="p-3">Plataforma Nube</td> | |
| <td class="p-3">Híbrido (Diseño)</td> | |
| <td class="p-3">Local-First (Git)</td> | |
| </tr> | |
| <tr class="bg-gray-800 border-b border-gray-700"> | |
| <td class="p-3 font-semibold">Rendimiento</td> | |
| <td class="p-3">Lento / Pesado</td> | |
| <td class="p-3">Rápido</td> | |
| <td class="p-3">Instantáneo</td> | |
| </tr> | |
| <tr class="bg-gray-800 border-b border-gray-700"> | |
| <td class="p-3 font-semibold">Privacidad</td> | |
| <td class="p-3">Baja (Nube)</td> | |
| <td class="p-3">Media</td> | |
| <td class="p-3">Total (Offline)</td> | |
| </tr> | |
| <tr class="bg-gray-800"> | |
| <td class="p-3 font-semibold">Ideal Para</td> | |
| <td class="p-3">Gobernanza</td> | |
| <td class="p-3">Diseño API</td> | |
| <td class="p-3">Desarrolladores</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| <!-- Slide 9: Título Parte II --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-5xl font-bold text-cyan-400">Parte II</h2> | |
| <h3 class="text-4xl text-white mt-4">Gestión de Proyectos Ágiles</h3> | |
| <p class="text-2xl text-gray-400 mt-6">Proceso Estricto vs. Flexibilidad Visual</p> | |
| </div> | |
| <!-- Placeholder GIF --> | |
| <div class="w-1/2"> | |
| <div class="gif-placeholder aspect-video"> | |
| <span class="text-gray-500 text-2xl font-semibold">Espacio para GIF</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 10: Herramienta Central: Jira --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6">Sistema Central: Jira</h2> | |
| <p class="text-xl text-gray-300 mb-4">Estándar (Atlassian) para gestión ágil a escala y seguimiento de incidencias.</p> | |
| <ul class="list-disc list-inside text-lg text-gray-300 space-y-2"> | |
| <li><b>Rol:</b> Imposición de procesos y auditoría.</li> | |
| <li><b>Conceptos:</b> Incidencias (Tickets), Flujos de Trabajo (Workflows), Tableros (Scrum/Kanban).</li> | |
| <li><b>Crítica:</b> Complejidad, rigidez y curva de aprendizaje pronunciada.</li> | |
| </ul> | |
| </div> | |
| <!-- Placeholder GIF --> | |
| <div class="w-1/2"> | |
| <div class="gif-placeholder aspect-video"> | |
| <span class="text-gray-500 text-2xl font-semibold">Espacio para GIF</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 11: Alternativa: Trello --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6">Alternativa: Trello</h2> | |
| <p class="text-xl text-gray-300 mb-4">Simplicidad visual radical (también de Atlassian).</p> | |
| <ul class="list-disc list-inside text-lg text-gray-300 space-y-2"> | |
| <li><b>Paradigma:</b> Kanban puro (Tableros, Listas, Tarjetas).</li> | |
| <li><b>Fortaleza:</b> Curva de aprendizaje nula. Extremadamente intuitivo.</li> | |
| <li><b>Debilidad:</b> Débil para métricas ágiles complejas (Scrum).</li> | |
| <li><b>Ideal para:</b> Equipos pequeños, tareas simples, no-técnicos.</li> | |
| </ul> | |
| </div> | |
| <!-- Placeholder GIF --> | |
| <div class="w-1/2"> | |
| <div class="gif-placeholder aspect-video"> | |
| <span class="text-gray-500 text-2xl font-semibold">Espacio para GIF</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 12: Alternativa: Asana --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6">Alternativa: Asana</h2> | |
| <p class="text-xl text-gray-300 mb-4">Busca el equilibrio entre la potencia (Jira) y la usabilidad (Trello).</p> | |
| <ul class="list-disc list-inside text-lg text-gray-300 space-y-2"> | |
| <li><b>Fortaleza:</b> Múltiples Vistas (Lista, Tablero, Cronograma/Gantt, Calendario).</li> | |
| <li><b>UX Superior:</b> Fomenta la adopción.</li> | |
| <li><b>Ideal para:</b> Equipos interdisciplinarios (Marketing, Ops, Devs) que necesitan ver datos de formas distintas.</li> | |
| </ul> | |
| </div> | |
| <!-- Placeholder GIF --> | |
| <div class="w-1/2"> | |
| <div class="gif-placeholder aspect-video"> | |
| <span class="text-gray-500 text-2xl font-semibold">Espacio para GIF</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 13: Tabla Comparativa Gestión (Full Width) --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex flex-col justify-center hidden opacity-0 bg-gray-800"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6 text-center">Comparativa: Gestión de Proyectos</h2> | |
| <table class="w-full text-left text-lg"> | |
| <thead class="bg-gray-700"> | |
| <tr> | |
| <th class="p-3">Característica</th> | |
| <th class="p-3">Jira</th> | |
| <th class="p-3">Trello</th> | |
| <th class="p-3">Asana</th> | |
| </tr> | |
| </thead> | |
| <tbody class="text-gray-300"> | |
| <tr class="bg-gray-800 border-b border-gray-700"> | |
| <td class="p-3 font-semibold">Filosofía</td> | |
| <td class="p-3">Imposición Proceso</td> | |
| <td class="p-3">Simplicidad Visual</td> | |
| <td class="p-3">Equilibrio (UX)</td> | |
| </tr> | |
| <tr class="bg-gray-800 border-b border-gray-700"> | |
| <td class="p-3 font-semibold">Curva Aprendizaje</td> | |
| <td class="p-3">Muy Alta</td> | |
| <td class="p-3">Nula</td> | |
| <td class="p-3">Moderada</td> | |
| </tr> | |
| <tr class="bg-gray-800 border-b border-gray-700"> | |
| <td class="p-3 font-semibold">Fortaleza</td> | |
| <td class="p-3">Trazabilidad</td> | |
| <td class="p-3">Facilidad de Uso</td> | |
| <td class="p-3">Múltiples Vistas</td> | |
| </tr> | |
| <tr class="bg-gray-800"> | |
| <td class="p-3 font-semibold">Equipo Ideal</td> | |
| <td class="p-3">Técnico (Devs)</td> | |
| <td class="p-3">No-Técnicos</td> | |
| <td class="p-3">Interdisciplinario</td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| <!-- Slide 14: Conclusión API --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6">Conclusión (APIs)</h2> | |
| <p class="text-xl text-gray-300">La elección depende del contexto:</p> | |
| <ul class="list-disc list-inside text-lg text-gray-300 space-y-3 mt-4"> | |
| <li><b>Postman:</b> Necesario para gobernanza corporativa y colaboración en nube síncrona obligatoria.</li> | |
| <li><b>Insomnia:</b> Ideal para diseño de APIs (GraphQL/OpenAPI) y un flujo híbrido (Git/Nube).</li> | |
| <li><b>Yaak:</b> Superior para el desarrollador individual que valora velocidad, privacidad y flujo *local-first* nativo de Git.</li> | |
| </ul> | |
| </div> | |
| <!-- Placeholder GIF --> | |
| <div class="w-1/2"> | |
| <div class="gif-placeholder aspect-video"> | |
| <span class="text-gray-500 text-2xl font-semibold">Espacio para GIF</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 15: Conclusión Gestión --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex items-center hidden opacity-0 bg-gray-800"> | |
| <div class="flex w-full space-x-8"> | |
| <!-- Contenido --> | |
| <div class="w-1/2 flex flex-col justify-center"> | |
| <h2 class="text-4xl font-bold text-cyan-400 mb-6">Conclusión (Gestión)</h2> | |
| <p class="text-xl text-gray-300">No hay "mejor", hay "adecuado":</p> | |
| <ul class="list-disc list-inside text-lg text-gray-300 space-y-3 mt-4"> | |
| <li><b>Jira:</b> Requerido para procesos ágiles estrictos, auditables y a gran escala (equipos técnicos maduros).</li> | |
| <li><b>Trello:</b> Imbatible en simplicidad y adopción rápida para tareas visuales o equipos no-técnicos.</li> | |
| <li><b>Asana:</b> El punto medio para equipos mixtos que necesitan potencia sin sacrificar la usabilidad.</li> | |
| </ul> | |
| </div> | |
| <!-- Placeholder GIF --> | |
| <div class="w-1/2"> | |
| <div class="gif-placeholder aspect-video"> | |
| <span class="text-gray-500 text-2xl font-semibold">Espacio para GIF</span> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Slide 16: Fin --> | |
| <div class="slide absolute inset-0 w-full h-full p-12 flex flex-col justify-center items-center text-center hidden opacity-0 bg-gray-800"> | |
| <h1 class="text-6xl font-bold text-cyan-400">Preguntas</h1> | |
| <h2 class="text-4xl text-white mt-10">Grupo 5</h2> | |
| </div> | |
| <!-- Controles de Navegación --> | |
| <button id="prev-slide" class="absolute bottom-6 left-6 bg-cyan-600 hover:bg-cyan-700 text-white font-bold py-2 px-6 rounded-full shadow-lg transition disabled:opacity-50 disabled:cursor-not-allowed z-10"> | |
| Anterior | |
| </button> | |
| <button id="next-slide" class="absolute bottom-6 right-6 bg-cyan-600 hover:bg-cyan-700 text-white font-bold py-2 px-6 rounded-full shadow-lg transition disabled:opacity-50 disabled:cursor-not-allowed z-10"> | |
| Siguiente | |
| </button> | |
| <div id="slide-counter" class="absolute bottom-7 left-1/2 -translate-x-1/2 text-gray-400 text-lg z-10"> | |
| 1 / 16 | |
| </div> | |
| </div> | |
| <script> | |
| document.addEventListener('DOMContentLoaded', () => { | |
| const slides = document.querySelectorAll('.slide'); | |
| const prevBtn = document.getElementById('prev-slide'); | |
| const nextBtn = document.getElementById('next-slide'); | |
| const counter = document.getElementById('slide-counter'); | |
| let currentSlide = 0; | |
| const totalSlides = slides.length; | |
| function showSlide(n) { | |
| // Ocultar slide actual | |
| slides[currentSlide].classList.add('opacity-0'); | |
| setTimeout(() => { | |
| slides[currentSlide].classList.add('hidden'); | |
| // Mostrar nuevo slide | |
| currentSlide = n; | |
| slides[currentSlide].classList.remove('hidden'); | |
| // Pequeño retraso para que 'hidden' se quite antes de la transición | |
| setTimeout(() => { | |
| slides[currentSlide].classList.remove('opacity-0'); | |
| }, 20); | |
| // Actualizar contador | |
| counter.textContent = `${currentSlide + 1} / ${totalSlides}`; | |
| // Actualizar estado de botones | |
| prevBtn.disabled = currentSlide === 0; | |
| nextBtn.disabled = currentSlide === totalSlides - 1; | |
| }, 400); // Coincide con la duración de la transición (0.4s) | |
| } | |
| // Event Listeners para botones | |
| nextBtn.addEventListener('click', () => { | |
| if (currentSlide < totalSlides - 1) { | |
| showSlide(currentSlide + 1); | |
| } | |
| }); | |
| prevBtn.addEventListener('click', () => { | |
| if (currentSlide > 0) { | |
| showSlide(currentSlide - 1); | |
| } | |
| }); | |
| // Event Listeners para teclado | |
| document.addEventListener('keydown', (e) => { | |
| if (e.key === 'ArrowRight' || e.key === 'PageDown' || e.key === ' ') { | |
| if (currentSlide < totalSlides - 1) { | |
| e.preventDefault(); | |
| showSlide(currentSlide + 1); | |
| } | |
| } else if (e.key === 'ArrowLeft' || e.key === 'PageUp') { | |
| if (currentSlide > 0) { | |
| e.preventDefault(); | |
| showSlide(currentSlide - 1); | |
| } | |
| } | |
| }); | |
| // Inicializar (asegura que el primer slide sea visible) | |
| slides[0].classList.remove('hidden'); | |
| slides[0].classList.remove('opacity-0'); | |
| prevBtn.disabled = true; | |
| counter.textContent = `1 / ${totalSlides}`; | |
| }); | |
| </script> | |
| <!-- Modal para mostrar GIF --> | |
| <div id="gif-modal" class="fixed inset-0 bg-black bg-opacity-80 hidden justify-center items-center z-50"> | |
| <div class="relative"> | |
| <img id="modal-image" src="" alt="GIF ampliado" class="max-w-[90vw] max-h-[80vh] rounded-lg shadow-2xl border border-gray-600"> | |
| <button id="close-modal" | |
| class="absolute top-2 right-2 bg-gray-800 hover:bg-gray-700 text-white rounded-full px-3 py-1 font-bold text-lg"> | |
| ✕ | |
| </button> | |
| </div> | |
| </div> | |
| <script> | |
| // Mostrar modal | |
| function openModal(gifSrc) { | |
| const modal = document.getElementById('gif-modal'); | |
| const modalImg = document.getElementById('modal-image'); | |
| modalImg.src = gifSrc; | |
| modal.classList.remove('hidden'); | |
| modal.classList.add('flex'); | |
| } | |
| // Cerrar modal | |
| function closeModal() { | |
| const modal = document.getElementById('gif-modal'); | |
| modal.classList.add('hidden'); | |
| modal.classList.remove('flex'); | |
| document.getElementById('modal-image').src = ""; | |
| } | |
| document.getElementById('close-modal').addEventListener('click', closeModal); | |
| // Cierra modal al hacer clic fuera del GIF | |
| document.getElementById('gif-modal').addEventListener('click', (e) => { | |
| if (e.target.id === 'gif-modal') closeModal(); | |
| }); | |
| // Cierra modal con tecla ESC | |
| document.addEventListener('keydown', (e) => { | |
| if (e.key === 'Escape') closeModal(); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |