CoolFace
Apppublic

silvaddss/magic-ratio-visual-alchemist

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
script.js260 linesDownload Raw Back to root
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});