| | 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); |
| | }); |
| |
|
| | |
| | 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() { |
| | |
| | this.numberDisplay.className = 'cinematic-number text-9xl md:text-[20rem] font-black tracking-tighter'; |
| | |
| | |
| | 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() { |
| | |
| | this.particlesContainer.innerHTML = ''; |
| | |
| | |
| | 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(); |
| | |
| | if (this.isLooping && this.isPlaying) { |
| | this.animationTimeout = setTimeout(() => { |
| | this.changeNumber(1); |
| | this.startAnimation(); |
| | }, 3000); |
| | } |
| | } |
| |
|
| | stopAnimation() { |
| | if (this.animationTimeout) { |
| | clearTimeout(this.animationTimeout); |
| | this.animationTimeout = null; |
| | } |
| | } |
| | } |
| |
|
| | |
| | document.addEventListener('DOMContentLoaded', () => { |
| | new CinematicNumbersApp(); |
| | }); |
| |
|
| | |
| | document.addEventListener('DOMContentLoaded', () => { |
| | if (typeof feather !== 'undefined') { |
| | feather.replace(); |
| | } |
| | }); |