|
|
| |
| function openImageEditor(imageSrc) { |
| const editor = document.querySelector('custom-image-editor'); |
| if (editor) { |
| editor.style.display = 'flex'; |
| |
| } |
| } |
| function generateFaceSwap() { |
| const resultsContainer = document.getElementById('results-container'); |
| const selectedImages = document.querySelectorAll('#image-preview img'); |
| const faceSelection = document.querySelectorAll('#face-selection .ring-purple-600'); |
| |
| if (selectedImages.length < 2) { |
| alert('Please upload at least 2 images for face swapping'); |
| return; |
| } |
|
|
| if (faceSelection.length < 2) { |
| alert('Please select at least 2 faces to swap'); |
| return; |
| } |
|
|
| |
| resultsContainer.innerHTML = ` |
| <div class="col-span-4 text-center py-12"> |
| <div class="animate-spin rounded-full h-12 w-12 border-b-2 border-purple-600 mx-auto mb-4"></div> |
| <p>Generating face swaps...</p> |
| </div> |
| `; |
|
|
| |
| const sourceImages = Array.from(selectedImages).map(img => img.src); |
|
|
| |
| setTimeout(() => { |
| |
| resultsContainer.innerHTML = ''; |
| |
| |
| const selectedFaceIds = Array.from(faceSelection).map(face => face.dataset.faceId); |
| |
| |
| for (let i = 0; i < 4; i++) { |
| const resultItem = document.createElement('div'); |
| resultItem.className = 'bg-white rounded-xl shadow-md overflow-hidden group'; |
| |
| |
| const faceId1 = selectedFaceIds[0]; |
| const faceId2 = selectedFaceIds[i % selectedFaceIds.length] || selectedFaceIds[1]; |
| |
| |
| const seed = (sourceImages.join('').length + parseInt(faceId1) + parseInt(faceId2)) % 1000; |
| |
| resultItem.innerHTML = ` |
| <img src="http://static.photos/people/640x360/${seed}" |
| class="w-full h-full object-cover transition group-hover:scale-105 cursor-pointer" |
| alt="Face swap result ${i+1}" |
| onclick="openImageEditor(this.src)"> |
| <div class="p-3"> |
| <h3 class="font-semibold">Result #${i+1}</h3> |
| <div class="flex justify-between items-center mt-2"> |
| <button class="text-purple-600 hover:text-purple-800 text-sm flex items-center" onclick="downloadImage(this)"> |
| <i data-feather="download" class="w-4 h-4 mr-1"></i> |
| Download |
| </button> |
| <button class="text-purple-600 hover:text-purple-800 text-sm flex items-center" onclick="openImageEditor(this.parentElement.parentElement.querySelector('img').src)"> |
| <i data-feather="edit" class="w-4 h-4 mr-1"></i> |
| Edit |
| </button> |
| </div> |
| </div> |
| `; |
| resultsContainer.appendChild(resultItem); |
| } |
| |
| if (typeof feather !== 'undefined') { |
| feather.replace(); |
| } |
| }, 2000); |
| } |
|
|
| function downloadImage(button) { |
| const img = button.closest('div').querySelector('img'); |
| const link = document.createElement('a'); |
| link.href = img.src; |
| link.download = `face-swap-${Date.now()}.jpg`; |
| document.body.appendChild(link); |
| link.click(); |
| document.body.removeChild(link); |
| } |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| if (typeof feather !== 'undefined') { |
| feather.replace(); |
| } |
|
|
| |
| const generateBtn = document.querySelector('main button:has(i[data-feather="refresh-cw"])'); |
| if (generateBtn) { |
| generateBtn.addEventListener('click', function(e) { |
| e.preventDefault(); |
| generateFaceSwap(); |
| }); |
| } |
|
|
| |
| document.addEventListener('click', function(e) { |
| if (e.target.closest('#image-preview img')) { |
| const imgSrc = e.target.src; |
| |
| console.log('Image clicked for face detection:', imgSrc); |
| } |
| }); |
| |
| const faceSelection = document.getElementById('face-selection'); |
| |
| |
| const fileInput = document.getElementById('file-input'); |
| if (fileInput) { |
| fileInput.addEventListener('change', function() { |
| const mockFaces = []; |
| const numFaces = Math.floor(Math.random() * 4) + 1; |
| |
| for (let i = 1; i <= numFaces; i++) { |
| const colors = ['bg-red-400', 'bg-blue-400', 'bg-green-400', 'bg-yellow-400']; |
| mockFaces.push({ |
| id: i, |
| name: `Face ${i}`, |
| color: colors[i % colors.length] |
| }); |
| } |
| |
| |
| faceSelection.innerHTML = ''; |
| |
| mockFaces.forEach(face => { |
| const faceElement = document.createElement('div'); |
| faceElement.className = `flex items-center justify-center w-16 h-16 rounded-full ${face.color} text-white cursor-pointer hover:opacity-80 transition`; |
| faceElement.textContent = face.name; |
| faceElement.dataset.faceId = face.id; |
| faceElement.addEventListener('click', function() { |
| this.classList.toggle('ring-2'); |
| this.classList.toggle('ring-purple-600'); |
| }); |
| faceSelection.appendChild(faceElement); |
| }); |
| }); |
| } |
| |
| faceSelection.innerHTML = ''; |
| mockFaces.forEach(face => { |
| const faceElement = document.createElement('div'); |
| faceElement.className = `flex items-center justify-center w-16 h-16 rounded-full ${face.color} text-white cursor-pointer hover:opacity-80 transition`; |
| faceElement.textContent = face.name; |
| faceElement.dataset.faceId = face.id; |
| faceElement.addEventListener('click', function() { |
| this.classList.toggle('ring-2'); |
| this.classList.toggle('ring-purple-600'); |
| }); |
| faceSelection.appendChild(faceElement); |
| }); |
| |
| |
| const fileInput = document.getElementById('file-input'); |
| if (fileInput) { |
| fileInput.addEventListener('change', function() { |
| const resultsContainer = document.getElementById('results-container'); |
| if (resultsContainer) { |
| resultsContainer.innerHTML = ` |
| <div class="text-center text-gray-500 py-12 col-span-4"> |
| <i data-feather="image" class="w-12 h-12 mx-auto mb-2"></i> |
| <p>Your face swaps will appear here</p> |
| </div> |
| `; |
| if (typeof feather !== 'undefined') { |
| feather.replace(); |
| } |
| } |
| }); |
| } |
| |
| const uploadArea = document.getElementById('upload-area'); |
| const fileInput = document.getElementById('file-input'); |
| const imagePreview = document.getElementById('image-preview'); |
| |
| |
| fileInput.addEventListener('change', function(e) { |
| handleFiles(e.target.files); |
| }); |
| |
| |
| uploadArea.addEventListener('dragover', function(e) { |
| e.preventDefault(); |
| uploadArea.classList.add('border-purple-500', 'bg-purple-50'); |
| }); |
| |
| uploadArea.addEventListener('dragleave', function() { |
| uploadArea.classList.remove('border-purple-500', 'bg-purple-50'); |
| }); |
| |
| uploadArea.addEventListener('drop', function(e) { |
| e.preventDefault(); |
| uploadArea.classList.remove('border-purple-500', 'bg-purple-50'); |
| if (e.dataTransfer.files.length) { |
| handleFiles(e.dataTransfer.files); |
| } |
| }); |
| function handleFiles(files) { |
| |
| Array.from(files).forEach(file => { |
| if (!file.type.match('image.*')) return; |
| |
| const reader = new FileReader(); |
| reader.onload = function(e) { |
| |
| const container = document.createElement('div'); |
| container.className = 'relative group'; |
| |
| |
| const img = document.createElement('img'); |
| img.src = e.target.result; |
| img.alt = file.name; |
| img.className = 'w-full h-full object-cover rounded-lg'; |
| |
| |
| const removeBtn = document.createElement('button'); |
| removeBtn.className = 'absolute top-2 right-2 bg-red-500 text-white rounded-full p-1 opacity-0 group-hover:opacity-100 transition-opacity'; |
| removeBtn.innerHTML = '<i data-feather="x"></i>'; |
| removeBtn.addEventListener('click', () => { |
| container.remove(); |
| if (typeof feather !== 'undefined') { |
| feather.replace(); |
| } |
| }); |
| |
| container.appendChild(img); |
| container.appendChild(removeBtn); |
| imagePreview.appendChild(container); |
| |
| if (typeof feather !== 'undefined') { |
| feather.replace(); |
| } |
| }; |
| reader.readAsDataURL(file); |
| }); |
| } |
| |
| }); |