Spaces:
Sleeping
Sleeping
| <html lang="es"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Generador de Panoramas</title> | |
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> | |
| <style> | |
| .preview-container { | |
| max-height: 300px; | |
| overflow-y: auto; | |
| } | |
| .community-image { | |
| max-width: 100%; | |
| height: auto; | |
| margin-bottom: 15px; | |
| border-radius: 8px; | |
| box-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
| } | |
| .upload-area { | |
| border: 2px dashed #ccc; | |
| border-radius: 8px; | |
| padding: 20px; | |
| text-align: center; | |
| background-color: #f8f9fa; | |
| cursor: pointer; | |
| } | |
| .upload-area:hover { | |
| border-color: #0d6efd; | |
| background-color: #f1f3f5; | |
| } | |
| #fileList { | |
| margin-top: 10px; | |
| padding: 0; | |
| list-style: none; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-light"> | |
| <div class="container py-5"> | |
| <div class="d-flex justify-content-between align-items-center mb-4"> | |
| <h1 class="mb-0">Generador de Panoramas</h1> | |
| <a href="{{ url_for('community') }}" class="btn btn-outline-primary"> | |
| <i class="bi bi-people"></i> Ver Comunidad | |
| </a> | |
| </div> | |
| {% with messages = get_flashed_messages() %} | |
| {% if messages %} | |
| {% for message in messages %} | |
| <div class="alert alert-info alert-dismissible fade show" role="alert"> | |
| {{ message }} | |
| <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> | |
| </div> | |
| {% endfor %} | |
| {% endif %} | |
| {% endwith %} | |
| <div class="row"> | |
| <div class="col-md-8 mb-4"> | |
| <div class="card"> | |
| <div class="card-body"> | |
| <h5 class="card-title">Crear Nuevo Panorama</h5> | |
| <form action="{{ url_for('upload_files') }}" method="post" enctype="multipart/form-data"> | |
| <div class="upload-area mb-3" id="dropZone" onclick="document.getElementById('fileInput').click();"> | |
| <i class="bi bi-cloud-upload"></i> | |
| <p class="mb-0">Haz clic aquí o arrastra tus imágenes</p> | |
| <small class="text-muted">Selecciona al menos 2 imágenes</small> | |
| <input type="file" id="fileInput" name="files[]" multiple accept=".jpg,.jpeg,.png" style="display: none;" onchange="updateFileList()"> | |
| </div> | |
| <ul id="fileList" class="list-group"></ul> | |
| <button type="submit" class="btn btn-primary mt-3" id="submitBtn" disabled>Crear Panorama</button> | |
| </form> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="col-md-4"> | |
| <div class="card"> | |
| <div class="card-body"> | |
| <h5 class="card-title">Instrucciones</h5> | |
| <div class="text-muted"> | |
| <p><strong>1.</strong> Selecciona al menos 2 imágenes que se solapen</p> | |
| <p><strong>2.</strong> Haz clic en "Crear Panorama"</p> | |
| <p><strong>3.</strong> Espera el procesamiento</p> | |
| <p><strong>4.</strong> Descarga o comparte tu resultado</p> | |
| <hr> | |
| <p class="text-center"> | |
| <a href="{{ url_for('community') }}" class="btn btn-sm btn-outline-primary"> | |
| Ver panoramas de la comunidad | |
| </a> | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="card mt-4"> | |
| <div class="card-body text-center"> | |
| <h5 class="card-title">Acerca De</h5> | |
| <button class="btn btn-link" onclick="alert('Este proyecto es creado por YahirDev, facilitando a los usuarios crear imágenes panorámicas para teléfonos y drones. Todo comenzó cuando compré un DJI que no tenía dicha opción, así que decidí crear mi propio programa que me permitiera crear imágenes de plano.');"> | |
| <i class="bi bi-info-circle"></i> Acerca De | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> | |
| <script> | |
| function updateFileList() { | |
| const input = document.getElementById('fileInput'); | |
| const fileList = document.getElementById('fileList'); | |
| const submitBtn = document.getElementById('submitBtn'); | |
| fileList.innerHTML = ''; | |
| submitBtn.disabled = input.files.length < 2; | |
| Array.from(input.files).forEach(file => { | |
| const li = document.createElement('li'); | |
| li.className = 'list-group-item d-flex justify-content-between align-items-center'; | |
| li.textContent = file.name; | |
| fileList.appendChild(li); | |
| }); | |
| } | |
| // Drag and drop functionality | |
| const dropZone = document.getElementById('dropZone'); | |
| ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { | |
| dropZone.addEventListener(eventName, preventDefaults, false); | |
| }); | |
| function preventDefaults(e) { | |
| e.preventDefault(); | |
| e.stopPropagation(); | |
| } | |
| ['dragenter', 'dragover'].forEach(eventName => { | |
| dropZone.addEventListener(eventName, highlight, false); | |
| }); | |
| ['dragleave', 'drop'].forEach(eventName => { | |
| dropZone.addEventListener(eventName, unhighlight, false); | |
| }); | |
| function highlight(e) { | |
| dropZone.classList.add('bg-light'); | |
| } | |
| function unhighlight(e) { | |
| dropZone.classList.remove('bg-light'); | |
| } | |
| dropZone.addEventListener('drop', handleDrop, false); | |
| function handleDrop(e) { | |
| const dt = e.dataTransfer; | |
| const files = dt.files; | |
| document.getElementById('fileInput').files = files; | |
| updateFileList(); | |
| } | |
| </script> | |
| </body> | |
| </html> | |