/** * Quantum Transition Animations * Provides dynamic transitions and particle effects for the Quantum NLP Framework */ // Wait for document to be fully loaded document.addEventListener('DOMContentLoaded', function() { // Initialize animations when page loads initQuantumAnimations(); // Add event listener for analyze button to trigger animations const analyzeBtn = document.getElementById('analyze-btn'); if (analyzeBtn) { analyzeBtn.addEventListener('click', function() { // Only trigger animation if form is valid const form = document.getElementById('process-form'); if (form.checkValidity()) { showQuantumTransition(); } }); // Enhanced button effects analyzeBtn.addEventListener('mouseover', function() { triggerSmallParticleEffect(this); }); } // Initialize text-to-vision transitions initTextToVisionTransitions(); // Check if results are present and apply animations const resultsContainer = document.getElementById('results-container'); if (resultsContainer && resultsContainer.children.length > 0) { applyResultsAnimations(resultsContainer); } }); /** * Initialize text-to-vision transitions with staggered timing */ function initTextToVisionTransitions() { const visionElements = document.querySelectorAll('.text-to-vision'); visionElements.forEach((elem, index) => { // Add a staggered delay for smoother visual effect const delay = 300 + (index * 150); setTimeout(() => { elem.classList.add('text-to-vision-active'); // Reset the animation after it completes to allow replaying setTimeout(() => { elem.classList.remove('text-to-vision-active'); }, 1500); }, delay); }); } /** * Apply animations to results container */ function applyResultsAnimations(container) { // Add entrance animation container.style.opacity = '0'; container.style.transform = 'translateY(20px)'; setTimeout(() => { container.style.transition = 'opacity 0.5s ease, transform 0.5s ease'; container.style.opacity = '1'; container.style.transform = 'translateY(0)'; // Apply smoke dispersion effect to each card const cards = container.querySelectorAll('.quantum-card'); cards.forEach((card, index) => { setTimeout(() => { card.classList.add('quantum-reveal'); }, 300 + (index * 150)); }); }, 200); } /** * Trigger a small particle effect around an element */ function triggerSmallParticleEffect(element) { // Create a few particles around the button const rect = element.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; // Create 5-10 particles const count = Math.floor(Math.random() * 5) + 5; for (let i = 0; i < count; i++) { const particle = document.createElement('div'); particle.className = 'quantum-particle'; // Random position around the element const angle = Math.random() * Math.PI * 2; const distance = Math.random() * 20 + 10; const x = centerX + Math.cos(angle) * distance; const y = centerY + Math.sin(angle) * distance; // Random size const size = Math.random() * 4 + 2; // Set styles particle.style.left = x + 'px'; particle.style.top = y + 'px'; particle.style.width = size + 'px'; particle.style.height = size + 'px'; particle.style.backgroundColor = getQuantumParticleColor(); // Add to body document.body.appendChild(particle); // Animate and remove setTimeout(() => { particle.remove(); }, 1000); } } /** * Initialize all quantum animations and effects */ function initQuantumAnimations() { // Create canvas for particle effects createParticleCanvas(); // Pre-load any assets needed for animations preloadAnimationAssets(); } /** * Create canvas for particle animations */ function createParticleCanvas() { const canvas = document.createElement('canvas'); canvas.id = 'quantum-particles'; canvas.className = 'particle-canvas'; canvas.width = window.innerWidth; canvas.height = window.innerHeight; // Add canvas to the body but keep it hidden initially canvas.style.display = 'none'; canvas.style.position = 'fixed'; canvas.style.top = 0; canvas.style.left = 0; canvas.style.pointerEvents = 'none'; canvas.style.zIndex = 1000; document.body.appendChild(canvas); // Handle window resize window.addEventListener('resize', function() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }); } /** * Preload any assets needed for animations */ function preloadAnimationAssets() { // Add any image preloading here if needed } /** * Show the quantum transition animation when analyzing text */ function showQuantumTransition() { // Get input and display areas const inputArea = document.querySelector('.card-body:has(#input_text)'); const resultsArea = document.querySelector('#results-container'); // Show loading overlay showLoadingOverlay(); // Show particle effects triggerParticleEffect(); // The actual form submission happens normally, but we add visual effects } /** * Show a quantum-themed loading overlay */ function showLoadingOverlay() { // Create overlay if it doesn't exist let overlay = document.getElementById('quantum-overlay'); if (!overlay) { overlay = document.createElement('div'); overlay.id = 'quantum-overlay'; overlay.innerHTML = `
Quantum Processing
`; document.body.appendChild(overlay); } // Show the overlay with animation overlay.style.display = 'flex'; setTimeout(() => { overlay.classList.add('active'); }, 10); } /** * Hide the quantum loading overlay */ function hideLoadingOverlay() { const overlay = document.getElementById('quantum-overlay'); if (overlay) { overlay.classList.remove('active'); setTimeout(() => { overlay.style.display = 'none'; }, 500); } } /** * Trigger the particle whirlwind effect */ function triggerParticleEffect() { const canvas = document.getElementById('quantum-particles'); if (!canvas) return; // Show canvas with fade-in canvas.style.display = 'block'; setTimeout(() => { canvas.classList.add('active'); }, 10); // Get canvas context const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); // Create particles for the whirlwind effect const particles = []; const particleCount = 150; // Initialize particles for (let i = 0; i < particleCount; i++) { particles.push({ x: canvas.width / 2, y: canvas.height / 2, size: Math.random() * 5 + 1, color: getQuantumParticleColor(), speedX: (Math.random() - 0.5) * 10, speedY: (Math.random() - 0.5) * 10, rotationRadius: Math.random() * 100 + 50, rotationSpeed: Math.random() * 0.1 + 0.02, rotationAngle: Math.random() * Math.PI * 2, opacity: Math.random() * 0.7 + 0.3, fadeSpeed: Math.random() * 0.02 + 0.005 }); } // Animation variables let frame = 0; const maxFrames = 120; // Animate particles function animateParticles() { // Clear canvas ctx.clearRect(0, 0, canvas.width, canvas.height); // Update and draw particles for (let i = 0; i < particles.length; i++) { const p = particles[i]; // Update rotation angle p.rotationAngle += p.rotationSpeed; // Calculate position with spiral effect const spiralFactor = 1 + (frame / maxFrames) * 3; const rotRadius = p.rotationRadius * (1 - frame / maxFrames); p.x = canvas.width / 2 + Math.cos(p.rotationAngle) * rotRadius * spiralFactor; p.y = canvas.height / 2 + Math.sin(p.rotationAngle) * rotRadius; // Add dispersion effect in later frames if (frame > maxFrames * 0.7) { p.x += p.speedX; p.y += p.speedY; p.opacity -= p.fadeSpeed; } // Draw particle ctx.globalAlpha = Math.max(0, p.opacity); ctx.fillStyle = p.color; ctx.beginPath(); ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); ctx.fill(); } // Increment frame frame++; // Continue animation or clean up if (frame <= maxFrames) { requestAnimationFrame(animateParticles); } else { // End animation with fade-out canvas.classList.remove('active'); // After fade-out, hide the canvas completely setTimeout(() => { canvas.style.display = 'none'; ctx.clearRect(0, 0, canvas.width, canvas.height); }, 300); } } // Start animation animateParticles(); // Set timeout to match form submission time setTimeout(function() { hideLoadingOverlay(); // Add reveal animation to results when they load const resultElements = document.querySelectorAll('.card'); resultElements.forEach((el, index) => { if (el.closest('#results-container')) { // Add a staggered delay for each card setTimeout(() => { el.classList.add('quantum-reveal'); }, index * 150); } }); }, 2000); // Adjust timing as needed to match server response time } /** * Get a color for quantum particles */ function getQuantumParticleColor() { const colors = [ '#4285F4', // Blue '#0F9D58', // Green '#DB4437', // Red '#F4B400', // Yellow '#9C27B0', // Purple '#00BCD4', // Cyan '#3F51B5' // Indigo ]; return colors[Math.floor(Math.random() * colors.length)]; } /** * Apply visualization effect to quantum results */ function visualizeQuantumResults() { const quantumScoreEl = document.querySelector('.quantum-score'); if (quantumScoreEl) { // Get the quantum score const score = parseFloat(quantumScoreEl.textContent); // Create a visualization canvas for the score createQuantumScoreVisualization(quantumScoreEl, score); // Apply visualization to the entire container const container = document.querySelector('.quantum-visualized'); if (container) { applyQuantumVisualization(container, score); } } } /** * Create a visualization for the quantum score */ function createQuantumScoreVisualization(element, score) { // Add special particle effects around the score const parentEl = element.closest('.text-end'); if (!parentEl) return; // Create a canvas for the visualization const canvas = document.createElement('canvas'); canvas.className = 'quantum-score-canvas'; canvas.width = 200; canvas.height = 100; canvas.style.position = 'absolute'; canvas.style.top = '0'; canvas.style.right = '0'; canvas.style.pointerEvents = 'none'; canvas.style.zIndex = '1'; // Insert canvas parentEl.style.position = 'relative'; parentEl.appendChild(canvas); // Create particles const ctx = canvas.getContext('2d'); const particles = []; const particleCount = Math.round(score * 50); // More particles for higher scores // Create particles based on score for (let i = 0; i < particleCount; i++) { particles.push({ x: canvas.width * 0.75, y: canvas.height * 0.5, size: Math.random() * 3 + 1, color: getScoreColor(score), speedX: (Math.random() - 0.5) * 2, speedY: (Math.random() - 0.5) * 2, opacity: Math.random() * 0.5 + 0.3, life: Math.random() * 100 + 50 }); } // Animate particles function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); let remainingParticles = 0; for (let i = 0; i < particles.length; i++) { const p = particles[i]; if (p.life > 0) { p.x += p.speedX; p.y += p.speedY; p.opacity = Math.max(0, p.opacity - 0.005); p.life--; ctx.globalAlpha = p.opacity; ctx.fillStyle = p.color; ctx.beginPath(); ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); ctx.fill(); remainingParticles++; } } if (remainingParticles > 0) { requestAnimationFrame(animate); } } // Start animation animate(); } /** * Apply quantum visualization to an element */ function applyQuantumVisualization(element, score) { // Add the visualized class element.classList.add('quantum-visualized'); // Create dynamic quantum effect based on score const intensity = score || 0.5; // Add a pulsing background effect element.style.setProperty('--quantum-pulse-intensity', intensity); // Create tumbleweed whirlwind effect createTumbleweeds(element, Math.round(intensity * 10)); } /** * Create tumbleweed whirlwind particles inside an element */ function createTumbleweeds(element, count) { for (let i = 0; i < count; i++) { const tumbleweed = document.createElement('div'); tumbleweed.className = 'tumbleweed'; // Random position within the element const rect = element.getBoundingClientRect(); const x = Math.random() * rect.width; const y = Math.random() * rect.height; // Random size const size = Math.random() * 20 + 10; // Set styles tumbleweed.style.left = x + 'px'; tumbleweed.style.top = y + 'px'; tumbleweed.style.width = size + 'px'; tumbleweed.style.height = size + 'px'; // Add to the element element.appendChild(tumbleweed); // Animate the tumbleweed animateTumbleweed(tumbleweed, rect); } } /** * Animate a tumbleweed particle */ function animateTumbleweed(element, containerRect) { const duration = Math.random() * 8000 + 4000; // 4-12 seconds let startTime = null; // The animation function function animate(timestamp) { if (!startTime) startTime = timestamp; const elapsed = timestamp - startTime; const progress = Math.min(elapsed / duration, 1); // Spiral motion const angle = progress * Math.PI * 6; // 3 full rotations const radius = progress * 100; // Expand outward const centerX = containerRect.width / 2; const centerY = containerRect.height / 2; const x = centerX + Math.cos(angle) * radius; const y = centerY + Math.sin(angle) * radius; // Apply position element.style.transform = `translate(${x}px, ${y}px) rotate(${angle * 180 / Math.PI}deg)`; // Fade out towards the end if (progress > 0.7) { element.style.opacity = 1 - ((progress - 0.7) / 0.3); } // Continue animation if not complete if (progress < 1) { requestAnimationFrame(animate); } else { // Remove element when animation completes element.remove(); } } // Start the animation requestAnimationFrame(animate); } /** * Get color based on score value */ function getScoreColor(score) { if (score < 0.3) return '#dc3545'; // Low - red if (score < 0.6) return '#ffc107'; // Medium - yellow if (score < 0.8) return '#0dcaf0'; // Good - cyan return '#198754'; // High - green }