class CinematicNumbersApp { constructor() { this.currentNumber = 1; this.currentAnimation = 'zoom'; this.isLooping = true; this.isPlaying = true; this.animationTimeout = null; this.initializeElements(); this.setupEventListeners(); this.startAnimation(); } initializeElements() { this.numberDisplay = document.getElementById('numberDisplay'); this.currentNumberSpan = document.getElementById('currentNumber'); this.animationTypeSelect = document.getElementById('animationType'); this.loopCheckbox = document.getElementById('loopAnimation'); this.playPauseButton = document.getElementById('playPause'); this.prevButton = document.getElementById('prevNumber'); this.nextButton = document.getElementById('nextNumber'); this.particlesContainer = document.getElementById('particles'); } setupEventListeners() { this.animationTypeSelect.addEventListener('change', (e) => { this.currentAnimation = e.target.value; this.applyAnimation(); }); this.loopCheckbox.addEventListener('change', (e) => { this.isLooping = e.target.checked; if (this.isLooping && this.isPlaying) { this.startAnimation(); } }); this.playPauseButton.addEventListener('click', () => { this.isPlaying = !this.isPlaying; if (this.isPlaying) { this.startAnimation(); } else { this.stopAnimation(); } }); this.prevButton.addEventListener('click', () => { this.changeNumber(-1); }); this.nextButton.addEventListener('click', () => { this.changeNumber(1); }); // Keyboard navigation document.addEventListener('keydown', (e) => { if (e.key === 'ArrowLeft') this.changeNumber(-1); if (e.key === 'ArrowRight') this.changeNumber(1); if (e.key === ' ') { this.isPlaying = !this.isPlaying; if (this.isPlaying) this.startAnimation(); else this.stopAnimation(); } }); } changeNumber(direction) { this.currentNumber += direction; if (this.currentNumber < 1) this.currentNumber = 10; if (this.currentNumber > 10) this.currentNumber = 1; this.updateDisplay(); this.applyAnimation(); } updateDisplay() { this.numberDisplay.textContent = this.currentNumber; this.numberDisplay.setAttribute('data-number', this.currentNumber); this.currentNumberSpan.textContent = this.currentNumber; } applyAnimation() { // Remove all animation classes this.numberDisplay.className = 'cinematic-number text-9xl md:text-[20rem] font-black tracking-tighter'; // Add current animation class switch(this.currentAnimation) { case 'zoom': this.numberDisplay.classList.add('zoom-animation'); break; case 'bounce': this.numberDisplay.classList.add('bounce-animation'); break; case 'smoke': this.numberDisplay.classList.add('smoke-animation'); this.createParticles(); break; case 'glitch': this.numberDisplay.classList.add('glitch-animation'); break; case 'pulse': this.numberDisplay.classList.add('pulse-animation'); break; } } createParticles() { // Clear existing particles this.particlesContainer.innerHTML = ''; // Create new particles for (let i = 0; i < 30; i++) { const particle = document.createElement('div'); particle.classList.add('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() * 0.5}s`; this.particlesContainer.appendChild(particle); } } startAnimation() { this.stopAnimation(); // Clear any existing timeout if (this.isLooping && this.isPlaying) { this.animationTimeout = setTimeout(() => { this.changeNumber(1); this.startAnimation(); }, 3000); // 3 second delay between numbers } } stopAnimation() { if (this.animationTimeout) { clearTimeout(this.animationTimeout); this.animationTimeout = null; } } } // Initialize the app when DOM is loaded document.addEventListener('DOMContentLoaded', () => { new CinematicNumbersApp(); }); // Handle feather icons replacement document.addEventListener('DOMContentLoaded', () => { if (typeof feather !== 'undefined') { feather.replace(); } });