Spaces:
Running
Running
| document.addEventListener('DOMContentLoaded', function() { | |
| const uploadArea = document.querySelector('.border-dashed'); | |
| const fileInput = document.getElementById('image-upload'); | |
| const previewBtn = document.getElementById('preview-btn'); | |
| const downloadBtn = document.getElementById('download-btn'); | |
| const previewContainer = document.getElementById('preview-container'); | |
| const animationStyle = document.getElementById('animation-style'); | |
| const promptContainer = document.getElementById('prompt-container'); | |
| const animationPrompt = document.getElementById('animation-prompt'); | |
| const intensitySlider = document.querySelector('input[type="range"]'); | |
| const speedSlider = document.querySelectorAll('input[type="range"]')[1]; | |
| let currentImage = null; | |
| let currentAnimation = null; | |
| let animationFrames = []; | |
| let frameIndex = 0; | |
| let animationInterval; | |
| // Show/hide prompt based on selection | |
| animationStyle.addEventListener('change', function() { | |
| if (this.value === 'custom') { | |
| promptContainer.classList.remove('hidden'); | |
| } else { | |
| promptContainer.classList.add('hidden'); | |
| } | |
| }); | |
| // Handle drag and drop | |
| uploadArea.addEventListener('click', () => fileInput.click()); | |
| uploadArea.addEventListener('dragover', (e) => { | |
| e.preventDefault(); | |
| uploadArea.classList.add('bg-gray-700'); | |
| }); | |
| uploadArea.addEventListener('dragleave', () => { | |
| uploadArea.classList.remove('bg-gray-700'); | |
| }); | |
| uploadArea.addEventListener('drop', (e) => { | |
| e.preventDefault(); | |
| uploadArea.classList.remove('bg-gray-700'); | |
| if (e.dataTransfer.files.length) { | |
| handleFileUpload(e.dataTransfer.files[0]); | |
| } | |
| }); | |
| fileInput.addEventListener('change', (e) => { | |
| if (e.target.files.length) { | |
| handleFileUpload(e.target.files[0]); | |
| } | |
| }); | |
| function handleFileUpload(file) { | |
| if (!file.type.match('image.*')) { | |
| alert('Please upload an image file'); | |
| return; | |
| } | |
| const reader = new FileReader(); | |
| reader.onload = function(e) { | |
| previewContainer.innerHTML = `<img src="${e.target.result}" alt="Uploaded preview" class="max-h-full max-w-full">`; | |
| currentImage = e.target.result; | |
| downloadBtn.disabled = false; | |
| }; | |
| reader.readAsDataURL(file); | |
| } | |
| previewBtn.addEventListener('click', function() { | |
| if (!currentImage) { | |
| alert('Please upload an image first'); | |
| return; | |
| } | |
| const img = previewContainer.querySelector('img'); | |
| if (img) { | |
| // Generate animation based on settings | |
| const intensity = parseInt(intensitySlider.value); | |
| const speed = parseInt(speedSlider.value); | |
| const prompt = animationStyle.value === 'custom' ? animationPrompt.value : animationStyle.options[animationStyle.selectedIndex].text; | |
| animationFrames = generateAnimationFrames( | |
| currentImage, | |
| prompt, | |
| animationStyle.value, | |
| intensity, | |
| speed | |
| ); | |
| playAnimation(animationFrames, speed); | |
| // Enable download button | |
| downloadBtn.disabled = false; | |
| } | |
| }); | |
| // Update animation when sliders change | |
| intensitySlider.addEventListener('input', function() { | |
| if (animationFrames.length > 0) { | |
| const speed = parseInt(speedSlider.value); | |
| animationFrames = generateAnimationFrames( | |
| currentImage, | |
| animationPrompt.value, | |
| animationStyle.value, | |
| parseInt(this.value), | |
| speed | |
| ); | |
| } | |
| }); | |
| speedSlider.addEventListener('input', function() { | |
| if (animationFrames.length > 0) { | |
| const speed = parseInt(this.value); | |
| playAnimation(animationFrames, speed); | |
| } | |
| }); | |
| function generateAnimationFrames(imageSrc, prompt, type, intensity = 5, speed = 5) { | |
| // This would call an API in real implementation | |
| // For demo, we generate basic frame transformations | |
| const frames = []; | |
| const frameCount = 10; // Number of animation frames | |
| const intensityFactor = intensity / 5; | |
| const speedFactor = speed / 5; | |
| for (let i = 0; i < frameCount; i++) { | |
| const progress = i / frameCount; | |
| const rotation = Math.sin(progress * Math.PI * 2) * 5 * intensityFactor; | |
| const scale = 1 + (Math.sin(progress * Math.PI) * 0.05 * intensityFactor); | |
| const translateX = Math.sin(progress * Math.PI * 2) * 10 * intensityFactor; | |
| const translateY = Math.sin(progress * Math.PI * 1.5) * 5 * intensityFactor; | |
| frames.push({ | |
| transform: `rotate(${rotation}deg) scale(${scale}) translate(${translateX}px, ${translateY}px)` | |
| }); | |
| } | |
| return frames; | |
| } | |
| function playAnimation(frames, speed) { | |
| clearInterval(animationInterval); | |
| const img = previewContainer.querySelector('img'); | |
| if (!img) return; | |
| frameIndex = 0; | |
| const frameDelay = 1000 / (speed * 2); // Adjust speed based on slider | |
| animationInterval = setInterval(() => { | |
| img.style.transform = frames[frameIndex].transform; | |
| frameIndex = (frameIndex + 1) % frames.length; | |
| }, frameDelay); | |
| } | |
| downloadBtn.addEventListener('click', function() { | |
| if (!currentImage) { | |
| alert('No image to download'); | |
| return; | |
| } | |
| // In a real app, you would generate the animated GIF here | |
| alert('Animation download would be generated here in a full implementation'); | |
| }); | |
| }); |