ProjectGenesis's picture
Create animated numbers (1–10) in the style of Netflix’s "Top 10" design.
1838d8f verified
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();
}
// Add animation class
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);
// Remove particles after animation
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);
}
}
// Initialize when DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
new NumberAnimationManager();
// Auto-play first animation
setTimeout(() => {
document.getElementById('play-btn').click();
}, 500);
});