Spaces:
Running
Running
File size: 8,492 Bytes
8bd9942 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
document.addEventListener('DOMContentLoaded', () => {
const uploadInput = document.getElementById('image-upload');
const uploadButton = document.getElementById('upload-button');
const uploadDropzone = document.getElementById('upload-dropzone');
const uploadedPreviews = document.getElementById('uploaded-previews');
const imageSpots = Array.from(document.querySelectorAll('.image-spot'));
const textPrompt = document.getElementById('text-prompt');
const remixButton = document.getElementById('remix-button');
const statusMessage = document.getElementById('status-message');
const remixResult = document.getElementById('remix-result');
const resultImage = document.getElementById('result-image');
const resultPlaceholder = document.getElementById('result-placeholder');
// Store base64 data for images in spots
const imageSpotData = Array(3).fill(null);
// Store original draggable elements created from uploaded images
const draggableImages = new Map(); // Map<id, {element, src}>
let uploadedImageCounter = 0;
// --- Utility Functions ---
const showStatus = (message, type = 'loading') => {
statusMessage.textContent = message;
statusMessage.className = `status-message ${type}`;
statusMessage.style.display = 'block';
};
const hideStatus = () => {
statusMessage.style.display = 'none';
statusMessage.textContent = '';
};
const clearResult = () => {
resultImage.style.display = 'none';
resultImage.src = '';
resultPlaceholder.style.display = 'block';
};
// --- File Upload Logic ---
uploadButton.addEventListener('click', () => uploadInput.click());
uploadInput.addEventListener('change', (event) => {
handleFiles(event.target.files);
});
uploadDropzone.addEventListener('dragover', (event) => {
event.preventDefault();
uploadDropzone.classList.add('drag-over');
});
uploadDropzone.addEventListener('dragleave', () => {
uploadDropzone.classList.remove('drag-over');
});
uploadDropzone.addEventListener('drop', (event) => {
event.preventDefault();
uploadDropzone.classList.remove('drag-over');
handleFiles(event.dataTransfer.files);
});
function handleFiles(files) {
if (files.length === 0) return;
Array.from(files).forEach(file => {
if (!file.type.startsWith('image/')) return;
const reader = new FileReader();
reader.onload = (e) => {
const imgId = `uploaded-img-${uploadedImageCounter++}`;
createDraggableImage(e.target.result, imgId);
};
reader.readAsDataURL(file);
});
}
function createDraggableImage(src, id) {
const wrapper = document.createElement('div');
wrapper.className = 'uploaded-image-wrapper';
wrapper.draggable = true;
wrapper.id = id;
const img = document.createElement('img');
img.src = src;
img.alt = `Uploaded image ${id}`;
const removeBtn = document.createElement('button');
removeBtn.className = 'remove-image';
removeBtn.textContent = 'x';
removeBtn.title = 'Remove image';
removeBtn.addEventListener('click', (e) => {
e.stopPropagation(); // Prevent drag event from firing
wrapper.remove();
draggableImages.delete(id);
// Also check if this image was in any spot and remove it
for (let i = 0; i < imageSpotData.length; i++) {
if (imageSpotData[i] && imageSpotData[i].id === id) {
clearImageSpot(imageSpots[i], i);
}
}
});
wrapper.appendChild(img);
wrapper.appendChild(removeBtn);
uploadedPreviews.appendChild(wrapper);
draggableImages.set(id, { element: wrapper, src: src });
wrapper.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', id);
e.dataTransfer.effectAllowed = 'copyMove';
// Optional: add a class to the original to make it transparent or similar
// e.target.classList.add('dragging');
});
// wrapper.addEventListener('dragend', (e) => {
// e.target.classList.remove('dragging');
// });
}
// --- Image Spot Drag & Drop Logic ---
imageSpots.forEach((spot) => {
spot.addEventListener('dragover', (event) => {
event.preventDefault();
spot.classList.add('drag-over');
event.dataTransfer.dropEffect = 'copy';
});
spot.addEventListener('dragleave', () => {
spot.classList.remove('drag-over');
});
spot.addEventListener('drop', (event) => {
event.preventDefault();
spot.classList.remove('drag-over');
const draggedId = event.dataTransfer.getData('text/plain');
const draggedImageData = draggableImages.get(draggedId);
if (draggedImageData) {
const spotIndex = parseInt(spot.dataset.index);
renderImageInSpot(spot, draggedImageData.src);
imageSpotData[spotIndex] = { src: draggedImageData.src, id: draggedId };
}
});
});
function renderImageInSpot(spotElement, imgSrc) {
const imgElement = spotElement.querySelector('.spot-image');
imgElement.src = imgSrc;
spotElement.classList.add('has-image');
imgElement.alt = `Image in spot ${spotElement.dataset.index + 1}`;
// Remove old image's alt if it exists and wasn't placeholder.
}
function clearImageSpot(spotElement, spotIndex) {
const imgElement = spotElement.querySelector('.spot-image');
imgElement.src = 'assets/img/placeholder.png'; // Reset to placeholder
spotElement.classList.remove('has-image');
imgElement.alt = `Image spot ${spotIndex + 1}`;
imageSpotData[spotIndex] = null;
}
// --- Remix Logic ---
remixButton.addEventListener('click', remixImages);
async function remixImages() {
hideStatus();
clearResult();
const images = imageSpotData.filter(data => data !== null);
const prompt = textPrompt.value.trim();
const selectedModel = document.querySelector('input[name="ai-model"]:checked').value;
if (images.length === 0) {
showStatus('Please drag at least one image into a spot.', 'error');
return;
}
if (!prompt) {
showStatus('Please enter a text prompt.', 'error');
return;
}
showStatus(`Remixing with ${selectedModel}... This is a simulation.`, 'loading');
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 3000)); // Simulate network delay
// In a real application, you would send `images` (base64 or URLs), `prompt`, and `selectedModel`
// to a backend API that integrates with Gemini-2 or GPT Image-1.
// The backend would then return the generated image's URL or base64.
// For simulation, we'll use a placeholder image based on the model
const placeholderResult = selectedModel === 'gemini-2'
? 'https://picsum.photos/seed/gemini/800/600?grayscale' // A bit more abstract
: 'https://picsum.photos/seed/gpt/800/600'; // Standard realistic
resultImage.src = placeholderResult;
resultImage.style.display = 'block';
resultPlaceholder.style.display = 'none';
showStatus('Remix successful! (Simulated)', 'success');
statusMessage.style.backgroundColor = '#d4edda'; // Light green for success
statusMessage.style.color = '#155724';
statusMessage.style.borderColor = '#28a745';
} catch (error) {
console.error('Remix error (simulated):', error);
showStatus('Failed to remix images. Please try again. (Simulated Error)', 'error');
}
}
});
// Initial state for result section
document.addEventListener('DOMContentLoaded', () => {
const resultImage = document.getElementById('result-image');
const resultPlaceholder = document.getElementById('result-placeholder');
resultImage.style.display = 'none';
resultPlaceholder.style.display = 'block';
}); |