|
|
class NumberAnimationManager { |
|
|
constructor() { |
|
|
this.container = document.getElementById('animation-container'); |
|
|
this.currentAnimation = null; |
|
|
this.isLooping = false; |
|
|
this.initializeControls(); |
|
|
} |
|
|
|
|
|
initializeControls() { |
|
|
const playBtn = document.getElementById('play-btn'); |
|
|
const loopToggle = document.getElementById('loop-toggle'); |
|
|
const animationSelect = document.getElementById('animation-select'); |
|
|
const numberSelect = document.getElementById('number-select'); |
|
|
|
|
|
playBtn.addEventListener('click', () => { |
|
|
this.playAnimation( |
|
|
numberSelect.value, |
|
|
animationSelect.value |
|
|
); |
|
|
}); |
|
|
|
|
|
loopToggle.addEventListener('click', () => { |
|
|
this.isLooping = !this.isLooping; |
|
|
loopToggle.textContent = `Loop: ${this.isLooping ? 'On' : 'Off'}`; |
|
|
if (this.isLooping && this.currentAnimation) { |
|
|
this.startLoop(); |
|
|
} |
|
|
}); |
|
|
} |
|
|
|
|
|
playAnimation(number, animationType) { |
|
|
this.clearContainer(); |
|
|
|
|
|
const numberElement = this.createNumberElement(number); |
|
|
this.container.appendChild(numberElement); |
|
|
|
|
|
if (animationType === 'smoke') { |
|
|
this.createParticles(); |
|
|
} |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
numberElement.classList.add(this.getAnimationClass(animationType)); |
|
|
}, 100); |
|
|
|
|
|
this.currentAnimation = { number, animationType }; |
|
|
|
|
|
if (this.isLooping) { |
|
|
this.startLoop(); |
|
|
} |
|
|
} |
|
|
|
|
|
createNumberElement(number) { |
|
|
const div = document.createElement('div'); |
|
|
div.className = 'cinematic-number'; |
|
|
div.textContent = number; |
|
|
div.setAttribute('data-number', number); |
|
|
return div; |
|
|
} |
|
|
|
|
|
createParticles() { |
|
|
const particlesContainer = document.createElement('div'); |
|
|
particlesContainer.className = 'particles'; |
|
|
|
|
|
for (let i = 0; i < 50; i++) { |
|
|
const particle = document.createElement('div'); |
|
|
particle.className = 'particle'; |
|
|
|
|
|
const angle = Math.random() * Math.PI * 2; |
|
|
const distance = 100 + Math.random() * 200; |
|
|
const tx = Math.cos(angle) * distance; |
|
|
const ty = Math.sin(angle) * distance; |
|
|
|
|
|
particle.style.setProperty('--tx', `${tx}px`); |
|
|
particle.style.setProperty('--ty', `${ty}px`); |
|
|
particle.style.left = '50%'; |
|
|
particle.style.top = '50%'; |
|
|
particle.style.animationDelay = `${Math.random() * 1}s`; |
|
|
|
|
|
particlesContainer.appendChild(particle); |
|
|
} |
|
|
|
|
|
this.container.appendChild(particlesContainer); |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
particlesContainer.remove(); |
|
|
}, 2000); |
|
|
} |
|
|
|
|
|
getAnimationClass(animationType) { |
|
|
const animationClasses = { |
|
|
'zoom': 'zoom-in', |
|
|
'bounce': 'bounce-in', |
|
|
'smoke': 'smoke-reveal', |
|
|
'glitch': 'glitch-flicker', |
|
|
'pulse': 'energy-pulse' |
|
|
}; |
|
|
|
|
|
return animationClasses[animationType] || 'zoom-in'; |
|
|
} |
|
|
|
|
|
clearContainer() { |
|
|
this.container.innerHTML = ''; |
|
|
} |
|
|
|
|
|
startLoop() { |
|
|
if (!this.isLooping || !this.currentAnimation) return; |
|
|
|
|
|
const { number, animationType } = this.currentAnimation; |
|
|
const durations = { |
|
|
'zoom': 3000, |
|
|
'bounce': 1500, |
|
|
'smoke': 4000, |
|
|
'glitch': 2500, |
|
|
'pulse': 3000 |
|
|
}; |
|
|
|
|
|
setInterval(() => { |
|
|
this.playAnimation(number, animationType); |
|
|
}, durations[animationType] || 3000); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
|
new NumberAnimationManager(); |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
document.getElementById('play-btn').click(); |
|
|
}, 500); |
|
|
}); |