silvaddss/magic-ratio-visual-alchemist
0
1 2document.addEventListener('DOMContentLoaded', () => {3 // Toggle sequence controls4 document.getElementById('create-sequence').addEventListener('change', (e) => {5 document.getElementById('sequence-controls').classList.toggle('hidden', !e.target.checked);6 } catch (error) {7 preview.innerHTML = `8 <div class="w-full h-full flex flex-col items-center justify-center text-red-400">9 <i data-feather="alert-circle" class="w-12 h-12 mb-4"></i>10 <p>Erro ao gerar vídeo. Tente novamente.</p>11 </div>12 `;13 feather.replace();14 }15 }16);17 // Add event listener for video play button18 preview.addEventListener('click', (e) => {19 if (e.target.closest('.w-16.h-16')) {20 alert(`Vídeo ${durationSlider.value}s está sendo reproduzido!`);21 }22});23 24// Adiciona animação para o efeito de scroll do vídeo25const style = document.createElement('style');26style.textContent = `27 @keyframes scroll {28 0% { transform: translateX(0); }29 100% { transform: translateX(-${100 - (100/6)}%); }30 }31 .animate-scroll {32 animation: scroll ${Math.floor(Math.random() * 10) + 10}s linear infinite;33 }34`;35document.head.appendChild(style);36 37// Adiciona JSZip para download de sequências38document.head.insertAdjacentHTML('beforeend', '<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>');39// Image ratio buttons40const ratioButtons = document.querySelectorAll('.ratio-btn');41 ratioButtons.forEach(button => {42 button.addEventListener('click', () => {43 ratioButtons.forEach(btn => btn.classList.remove('active', 'bg-purple-600', 'bg-indigo-600'));44 button.classList.add('active');45 46 if(button.id.includes('16-9')) {47 button.classList.add('bg-purple-600');48 } else {49 button.classList.add('bg-indigo-600');50 }51 52 updatePreviewAspectRatio();53 });54 });55 56 // Size slider57 const sizeSlider = document.getElementById('size-slider');58 const currentSize = document.getElementById('current-size');59 sizeSlider.addEventListener('input', () => {60 currentSize.textContent = `${sizeSlider.value}px`;61 });62 63 // Duration slider64 const durationSlider = document.getElementById('duration-slider');65 const currentDuration = document.getElementById('current-duration');66 durationSlider.addEventListener('input', () => {67 currentDuration.textContent = `${durationSlider.value}s`;68 });69 70 // Generate image button71 const generateImageBtn = document.getElementById('generate-image');72 generateImageBtn.addEventListener('click', generateImage);73 74 // Generate video button75 const generateVideoBtn = document.getElementById('generate-video');76 generateVideoBtn.addEventListener('click', generateVideo);77 78 function updatePreviewAspectRatio() {79 const preview = document.getElementById('preview-container');80 if(document.querySelector('.ratio-btn.active').id.includes('16-9')) {81 preview.classList.add('aspect-video');82 preview.classList.remove('aspect-[9/16]');83 } else {84 preview.classList.remove('aspect-video');85 preview.classList.add('aspect-[9/16]');86 }87 }88 async function generateImage() {89 const preview = document.getElementById('preview-container');90 const activeRatio = document.querySelector('.ratio-btn.active').id.includes('16-9') ? '16:9' : '9:16';91 const resolution = parseInt(document.getElementById('resolution-select').value);92 const width = activeRatio === '16:9' ? resolution : Math.round(resolution * 9/16);93 const height = activeRatio === '16:9' ? Math.round(resolution * 9/16) : resolution;94 const prompt = document.getElementById('image-prompt').value || "random landscape";95 const style = document.getElementById('style-select').value;96 const createSequence = document.getElementById('create-sequence').checked;97 const sequenceCount = createSequence ? parseInt(document.querySelector('#sequence-controls input').value) : 1;98 99 // Show loading state100 preview.innerHTML = `101 <div class="w-full h-full flex flex-col items-center justify-center">102 <div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-purple-500 mb-4"></div>103 <p class="text-purple-200">Gerando ${createSequence && sequenceCount > 1 ? 'sequência de imagens' : 'imagem'}...</p>104 </div>105 `;106 107 try {108 // Generate using static.photos service for better quality and style matching109 await new Promise(resolve => setTimeout(resolve, 1500));110 111 preview.innerHTML = '';112const styleToCategory = {113 realistic: "nature",114 anime: "anime",115 fantasy: "fantasy",116 cyberpunk: "neon",117 "oil-painting": "painting",118 watercolor: "watercolor",119 minimalist: "minimalist",120 cinematic: "cinematic"121 };122const category = styleToCategory[style] || "abstract";123 124 if (createSequence && sequenceCount > 1) {125 const gridClasses = sequenceCount <= 4 ? 'grid-cols-2' : 'grid-cols-3';126 preview.className = `relative overflow-hidden rounded-lg bg-black/40 grid ${gridClasses} md:grid-cols-4 gap-2 p-2`;127 128 for (let i = 0; i < sequenceCount; i++) {129 const seed = Math.floor(Math.random() * 1000) + 1 + i;130 const imgContainer = document.createElement('div');131 imgContainer.className = 'relative overflow-hidden rounded';132 133 const img = document.createElement('img');134 img.src = `https://source.unsplash.com/random/${width}x${height}/?${encodeURIComponent(prompt)},${category}&sig=${seed}`;135img.alt = `Generated ${style} image: ${prompt}`;136 img.className = 'w-full h-full object-cover';137 img.loading = 'lazy';138 139 imgContainer.appendChild(img);140 preview.appendChild(imgContainer);141 }142 } else {143 const seed = Math.floor(Math.random() * 1000) + 1;144 const img = document.createElement('img');145 img.src = `https://source.unsplash.com/random/${width}x${height}/?${encodeURIComponent(prompt)},${category}&sig=${seed}`;146img.alt = `Generated ${style} image: ${prompt}`;147 img.className = 'w-full h-full object-cover';148 preview.appendChild(img);149 }150// Update download button functionality151 const downloadBtn = document.querySelector('.download-btn');152 downloadBtn.onclick = () => {153 if (createSequence && sequenceCount > 1) {154 const zip = new JSZip();155 const imgFolder = zip.folder("sequence_images");156 157 preview.querySelectorAll('img').forEach((img, index) => {158 fetch(img.src)159 .then(response => response.blob())160 .then(blob => {161 imgFolder.file(`image_${index+1}.jpg`, blob);162 if (index === sequenceCount - 1) {163 zip.generateAsync({type:"blob"}).then(content => {164 const link = document.createElement('a');165 link.href = URL.createObjectURL(content);166 link.download = `image_sequence_${width}x${height}.zip`;167 link.click();168 });169 }170 });171 });172 } else {173 const img = preview.querySelector('img');174 if (img) {175 const link = document.createElement('a');176 link.href = img.src;177 link.download = `image_${width}x${height}_${style}.jpg`;178 link.click();179 }180 }181 };182}183 async function generateVideo() {184 const preview = document.getElementById('preview-container');185 const activeRatio = document.querySelector('#video-16-9').classList.contains('active') ? '16:9' : '9:16';186 const duration = parseInt(durationSlider.value);187 const theme = document.getElementById('video-prompt').value || "abstract motion";188 189 // Show loading state190 preview.innerHTML = `191 <div class="w-full h-full flex flex-col items-center justify-center">192 <div class="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-purple-500 mb-4"></div>193 <p class="text-purple-200">Gerando vídeo ${duration}s...</p>194 </div>195 `;196 197 try {198 await new Promise(resolve => setTimeout(resolve, 2000));199 200 preview.innerHTML = '';201 202 // Create realistic video preview203 const videoContainer = document.createElement('div');204 videoContainer.className = 'relative w-full h-full overflow-hidden rounded-lg';205 206 // Create animated frames207 const framesContainer = document.createElement('div');208 framesContainer.className = 'absolute inset-0 flex animate-scroll';209 const styleToCategory = {210 realistic: "nature",211 anime: "anime",212 fantasy: "fantasy",213 cyberpunk: "neon",214 cinematic: "cinematic"215 };216const category = styleToCategory[theme.toLowerCase().includes('nature') ? 'realistic' : 217 theme.toLowerCase().includes('cyber') ? 'cyberpunk' : 218 theme.toLowerCase().includes('cinematic') ? 'cinematic' : 'abstract'] || "abstract";219 220 const frameCount = Math.min(10, Math.max(3, Math.floor(duration/2)));221 const width = activeRatio === '16:9' ? 800 : 450;222 const height = activeRatio === '16:9' ? 450 : 800;223 224 for (let i = 0; i < frameCount; i++) {225 const frame = document.createElement('div');226 frame.className = 'h-full w-full flex-shrink-0';227 228 const img = document.createElement('img');229 img.src = `http://static.photos/${category}/${width}x${height}?seed=${i+1000}`;230img.alt = `Video frame ${i+1}`;231 img.className = 'w-full h-full object-cover';232 233 frame.appendChild(img);234 framesContainer.appendChild(frame);235 }236 237 // Play button238 const overlay = document.createElement('div');239 overlay.className = 'absolute inset-0 flex items-center justify-center bg-black/30 cursor-pointer';240 overlay.onclick = () => {241 alert(`Vídeo de ${duration}s (${activeRatio}) sobre "${theme}" sendo reproduzido!`);242 };243 244 const playBtn = document.createElement('div');245 playBtn.className = 'w-16 h-16 rounded-full bg-purple-600/80 flex items-center justify-center';246 playBtn.innerHTML = '<i data-feather="play" class="w-8 h-8 text-white ml-1"></i>';247 248 overlay.appendChild(playBtn);249 videoContainer.appendChild(framesContainer);250 videoContainer.appendChild(overlay);251 preview.appendChild(videoContainer);252 253 feather.replace();254 255 // Download button functionality256 document.querySelector('.download-btn').onclick = () => {257 alert(`Seu vídeo de ${duration}s está pronto! Na versão premium, você pode baixá-lo em diferentes formatos.`);258 };259}260});