maximus-im / animations.js
lattmamb's picture
Upload 47 files
8beb2b1
/**
* 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 = `
<div class="quantum-loader">
<div class="quantum-spinner">
<div class="q-orbit q-orbit-1"></div>
<div class="q-orbit q-orbit-2"></div>
<div class="q-orbit q-orbit-3"></div>
<div class="q-core"></div>
</div>
<div class="quantum-message">Quantum Processing</div>
</div>
`;
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
}