Create animated numbers (1–10) in the style of Netflix’s "Top 10" design.
Browse files🎨 Visual Style:
Bold, oversized, cinematic numbers
3D bevel or extruded look
Black or deep gradient background
Dramatic red lighting or glowing edge accents (like Netflix’s brand style)
Metallic or glassy surfaces with depth and shadows
🎥 Animation Variations (generate a few options):
Slow Zoom In with light shimmer
Pop-in Bounce (dynamic entry with scale bounce)
Smoke or Particle Reveal (number emerges through cinematic particles)
Glitch Flicker for a digital/glassy feel
Energy Pulse where the number briefly surges with light
📐 Framing & Layout:
Centered, full-screen number focus
No extra UI, no labels — just the animated number
🧱 Output Needed:
Separate animation clips for each number (1–10)
Transparent or dark background
Looping and non-looping options
- README.md +8 -5
- components/number-animations.js +140 -0
- index.html +64 -19
- script.js +161 -0
- style.css +202 -18
README.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
| 1 |
---
|
| 2 |
-
title: Cinematic Countdown Canvas
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Cinematic Countdown Canvas 🎬
|
| 3 |
+
colorFrom: green
|
| 4 |
+
colorTo: purple
|
| 5 |
+
emoji: 🐳
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
tags:
|
| 9 |
+
- deepsite-v3
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Welcome to your new DeepSite project!
|
| 13 |
+
This project was created with [DeepSite](https://huggingface.co/deepsite).
|
components/number-animations.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class CinematicNumber extends HTMLElement {
|
| 2 |
+
constructor() {
|
| 3 |
+
super();
|
| 4 |
+
this.attachShadow({ mode: 'open' });
|
| 5 |
+
}
|
| 6 |
+
|
| 7 |
+
connectedCallback() {
|
| 8 |
+
this.render();
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
static get observedAttributes() {
|
| 12 |
+
return ['number', 'animation', 'loop'];
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
attributeChangedCallback(name, oldValue, newValue) {
|
| 16 |
+
if (oldValue !== newValue) {
|
| 17 |
+
this.render();
|
| 18 |
+
}
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
+
render() {
|
| 22 |
+
const number = this.getAttribute('number') || '1';
|
| 23 |
+
const animation = this.getAttribute('animation') || 'zoom';
|
| 24 |
+
const loop = this.getAttribute('loop') === 'true';
|
| 25 |
+
|
| 26 |
+
this.shadowRoot.innerHTML = `
|
| 27 |
+
<style>
|
| 28 |
+
:host {
|
| 29 |
+
display: block;
|
| 30 |
+
font-family: 'Bebas Neue', sans-serif;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
.number-container {
|
| 34 |
+
position: relative;
|
| 35 |
+
display: inline-block;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
.cinematic-number {
|
| 39 |
+
font-size: 20rem;
|
| 40 |
+
font-weight: 900;
|
| 41 |
+
letter-spacing: -0.05em;
|
| 42 |
+
background: linear-gradient(145deg, #8b0000, #ff0000, #8b0000);
|
| 43 |
+
background-size: 200% 200%;
|
| 44 |
+
-webkit-background-clip: text;
|
| 45 |
+
background-clip: text;
|
| 46 |
+
-webkit-text-fill-color: transparent;
|
| 47 |
+
text-shadow:
|
| 48 |
+
0 0 30px rgba(255, 0, 0, 0.8),
|
| 49 |
+
0 0 60px rgba(255, 0, 0, 0.6),
|
| 50 |
+
0 0 90px rgba(255, 0, 0, 0.4),
|
| 51 |
+
2px 2px 4px rgba(0, 0, 0, 0.8),
|
| 52 |
+
-2px -2px 4px rgba(255, 255, 255, 0.1);
|
| 53 |
+
animation: shimmer 3s ease-in-out infinite;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
@keyframes shimmer {
|
| 57 |
+
0%, 100% {
|
| 58 |
+
background-position: 0% 50%;
|
| 59 |
+
filter: brightness(1);
|
| 60 |
+
}
|
| 61 |
+
50% {
|
| 62 |
+
background-position: 100% 50%;
|
| 63 |
+
filter: brightness(1.2);
|
| 64 |
+
}
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
.particles {
|
| 68 |
+
position: absolute;
|
| 69 |
+
top: 0;
|
| 70 |
+
left: 0;
|
| 71 |
+
right: 0;
|
| 72 |
+
bottom: 0;
|
| 73 |
+
pointer-events: none;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
.particle {
|
| 77 |
+
position: absolute;
|
| 78 |
+
width: 4px;
|
| 79 |
+
height: 4px;
|
| 80 |
+
background: #ff0000;
|
| 81 |
+
border-radius: 50%;
|
| 82 |
+
animation: particleFloat 2s ease-out forwards;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
@keyframes particleFloat {
|
| 86 |
+
0% {
|
| 87 |
+
transform: translate(0, 0) scale(1);
|
| 88 |
+
opacity: 1;
|
| 89 |
+
}
|
| 90 |
+
100% {
|
| 91 |
+
transform: translate(var(--tx), var(--ty)) scale(0);
|
| 92 |
+
opacity: 0;
|
| 93 |
+
}
|
| 94 |
+
}
|
| 95 |
+
</style>
|
| 96 |
+
<div class="number-container">
|
| 97 |
+
<div class="cinematic-number">${number}</div>
|
| 98 |
+
<div class="particles"></div>
|
| 99 |
+
</div>
|
| 100 |
+
`;
|
| 101 |
+
|
| 102 |
+
this.applyAnimation(animation);
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
applyAnimation(animationType) {
|
| 106 |
+
const numberElement = this.shadowRoot.querySelector('.cinematic-number');
|
| 107 |
+
const particlesContainer = this.shadowRoot.querySelector('.particles');
|
| 108 |
+
|
| 109 |
+
// Remove existing particles
|
| 110 |
+
particlesContainer.innerHTML = '';
|
| 111 |
+
|
| 112 |
+
switch(animationType) {
|
| 113 |
+
case 'smoke':
|
| 114 |
+
this.createParticles(particlesContainer);
|
| 115 |
+
break;
|
| 116 |
+
}
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
createParticles(container) {
|
| 120 |
+
for (let i = 0; i < 20; i++) {
|
| 121 |
+
const particle = document.createElement('div');
|
| 122 |
+
particle.classList.add('particle');
|
| 123 |
+
|
| 124 |
+
const angle = Math.random() * Math.PI * 2;
|
| 125 |
+
const distance = 80 + Math.random() * 120;
|
| 126 |
+
const tx = Math.cos(angle) * distance;
|
| 127 |
+
const ty = Math.sin(angle) * distance;
|
| 128 |
+
|
| 129 |
+
particle.style.setProperty('--tx', `${tx}px`);
|
| 130 |
+
particle.style.setProperty('--ty', `${ty}px`);
|
| 131 |
+
particle.style.left = '50%';
|
| 132 |
+
particle.style.top = '50%';
|
| 133 |
+
particle.style.animationDelay = `${Math.random() * 0.3}s`;
|
| 134 |
+
|
| 135 |
+
container.appendChild(particle);
|
| 136 |
+
}
|
| 137 |
+
}
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
customElements.define('cinematic-number', CinematicNumber);
|
index.html
CHANGED
|
@@ -1,19 +1,64 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
</
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>Cinematic Countdown Canvas</title>
|
| 7 |
+
<link rel="stylesheet" href="style.css">
|
| 8 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 9 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 10 |
+
<script src="https://unpkg.com/feather-icons"></script>
|
| 11 |
+
</head>
|
| 12 |
+
<body class="bg-black min-h-screen overflow-hidden">
|
| 13 |
+
<div id="app" class="relative w-full h-screen flex items-center justify-center">
|
| 14 |
+
<!-- Animation Controls -->
|
| 15 |
+
<div class="absolute top-4 left-4 z-10 bg-black/70 backdrop-blur-sm rounded-lg p-4 text-white">
|
| 16 |
+
<h3 class="font-bold mb-2">Animation Controls</h3>
|
| 17 |
+
<div class="space-y-2">
|
| 18 |
+
<select id="animationType" class="w-full bg-gray-800 text-white rounded px-2 py-1">
|
| 19 |
+
<option value="zoom">Zoom In with Shimmer</option>
|
| 20 |
+
<option value="bounce">Pop-in Bounce</option>
|
| 21 |
+
<option value="smoke">Smoke Reveal</option>
|
| 22 |
+
<option value="glitch">Glitch Flicker</option>
|
| 23 |
+
<option value="pulse">Energy Pulse</option>
|
| 24 |
+
</select>
|
| 25 |
+
<div class="flex gap-2">
|
| 26 |
+
<button id="prevNumber" class="flex-1 bg-red-600 hover:bg-red-700 text-white rounded px-2 py-1 transition-colors">
|
| 27 |
+
<i data-feather="chevron-left" class="w-4 h-4"></i>
|
| 28 |
+
</button>
|
| 29 |
+
<button id="nextNumber" class="flex-1 bg-red-600 hover:bg-red-700 text-white rounded px-2 py-1 transition-colors">
|
| 30 |
+
<i data-feather="chevron-right" class="w-4 h-4"></i>
|
| 31 |
+
</button>
|
| 32 |
+
</div>
|
| 33 |
+
<label class="flex items-center gap-2">
|
| 34 |
+
<input type="checkbox" id="loopAnimation" checked>
|
| 35 |
+
<span class="text-sm">Loop Animation</span>
|
| 36 |
+
</label>
|
| 37 |
+
<button id="playPause" class="w-full bg-red-600 hover:bg-red-700 text-white rounded px-2 py-1 transition-colors">
|
| 38 |
+
Play/Pause
|
| 39 |
+
</button>
|
| 40 |
+
</div>
|
| 41 |
+
</div>
|
| 42 |
+
|
| 43 |
+
<!-- Number Display -->
|
| 44 |
+
<div id="numberContainer" class="relative">
|
| 45 |
+
<div id="numberDisplay" class="cinematic-number text-9xl md:text-[20rem] font-black tracking-tighter">
|
| 46 |
+
1
|
| 47 |
+
</div>
|
| 48 |
+
<div id="particles" class="absolute inset-0 pointer-events-none"></div>
|
| 49 |
+
</div>
|
| 50 |
+
|
| 51 |
+
<!-- Current Number Indicator -->
|
| 52 |
+
<div class="absolute bottom-4 left-1/2 transform -translate-x-1/2 bg-black/70 backdrop-blur-sm rounded-full px-4 py-2 text-white text-sm">
|
| 53 |
+
Number <span id="currentNumber">1</span>/10
|
| 54 |
+
</div>
|
| 55 |
+
</div>
|
| 56 |
+
|
| 57 |
+
<script src="components/number-animations.js"></script>
|
| 58 |
+
<script src="script.js"></script>
|
| 59 |
+
<script>
|
| 60 |
+
feather.replace();
|
| 61 |
+
</script>
|
| 62 |
+
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
|
| 63 |
+
</body>
|
| 64 |
+
</html>
|
script.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class CinematicNumbersApp {
|
| 2 |
+
constructor() {
|
| 3 |
+
this.currentNumber = 1;
|
| 4 |
+
this.currentAnimation = 'zoom';
|
| 5 |
+
this.isLooping = true;
|
| 6 |
+
this.isPlaying = true;
|
| 7 |
+
this.animationTimeout = null;
|
| 8 |
+
|
| 9 |
+
this.initializeElements();
|
| 10 |
+
this.setupEventListeners();
|
| 11 |
+
this.startAnimation();
|
| 12 |
+
}
|
| 13 |
+
|
| 14 |
+
initializeElements() {
|
| 15 |
+
this.numberDisplay = document.getElementById('numberDisplay');
|
| 16 |
+
this.currentNumberSpan = document.getElementById('currentNumber');
|
| 17 |
+
this.animationTypeSelect = document.getElementById('animationType');
|
| 18 |
+
this.loopCheckbox = document.getElementById('loopAnimation');
|
| 19 |
+
this.playPauseButton = document.getElementById('playPause');
|
| 20 |
+
this.prevButton = document.getElementById('prevNumber');
|
| 21 |
+
this.nextButton = document.getElementById('nextNumber');
|
| 22 |
+
this.particlesContainer = document.getElementById('particles');
|
| 23 |
+
}
|
| 24 |
+
|
| 25 |
+
setupEventListeners() {
|
| 26 |
+
this.animationTypeSelect.addEventListener('change', (e) => {
|
| 27 |
+
this.currentAnimation = e.target.value;
|
| 28 |
+
this.applyAnimation();
|
| 29 |
+
});
|
| 30 |
+
|
| 31 |
+
this.loopCheckbox.addEventListener('change', (e) => {
|
| 32 |
+
this.isLooping = e.target.checked;
|
| 33 |
+
if (this.isLooping && this.isPlaying) {
|
| 34 |
+
this.startAnimation();
|
| 35 |
+
}
|
| 36 |
+
});
|
| 37 |
+
|
| 38 |
+
this.playPauseButton.addEventListener('click', () => {
|
| 39 |
+
this.isPlaying = !this.isPlaying;
|
| 40 |
+
if (this.isPlaying) {
|
| 41 |
+
this.startAnimation();
|
| 42 |
+
} else {
|
| 43 |
+
this.stopAnimation();
|
| 44 |
+
}
|
| 45 |
+
});
|
| 46 |
+
|
| 47 |
+
this.prevButton.addEventListener('click', () => {
|
| 48 |
+
this.changeNumber(-1);
|
| 49 |
+
});
|
| 50 |
+
|
| 51 |
+
this.nextButton.addEventListener('click', () => {
|
| 52 |
+
this.changeNumber(1);
|
| 53 |
+
});
|
| 54 |
+
|
| 55 |
+
// Keyboard navigation
|
| 56 |
+
document.addEventListener('keydown', (e) => {
|
| 57 |
+
if (e.key === 'ArrowLeft') this.changeNumber(-1);
|
| 58 |
+
if (e.key === 'ArrowRight') this.changeNumber(1);
|
| 59 |
+
if (e.key === ' ') {
|
| 60 |
+
this.isPlaying = !this.isPlaying;
|
| 61 |
+
if (this.isPlaying) this.startAnimation();
|
| 62 |
+
else this.stopAnimation();
|
| 63 |
+
}
|
| 64 |
+
});
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
changeNumber(direction) {
|
| 68 |
+
this.currentNumber += direction;
|
| 69 |
+
|
| 70 |
+
if (this.currentNumber < 1) this.currentNumber = 10;
|
| 71 |
+
if (this.currentNumber > 10) this.currentNumber = 1;
|
| 72 |
+
|
| 73 |
+
this.updateDisplay();
|
| 74 |
+
this.applyAnimation();
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
updateDisplay() {
|
| 78 |
+
this.numberDisplay.textContent = this.currentNumber;
|
| 79 |
+
this.numberDisplay.setAttribute('data-number', this.currentNumber);
|
| 80 |
+
this.currentNumberSpan.textContent = this.currentNumber;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
applyAnimation() {
|
| 84 |
+
// Remove all animation classes
|
| 85 |
+
this.numberDisplay.className = 'cinematic-number text-9xl md:text-[20rem] font-black tracking-tighter';
|
| 86 |
+
|
| 87 |
+
// Add current animation class
|
| 88 |
+
switch(this.currentAnimation) {
|
| 89 |
+
case 'zoom':
|
| 90 |
+
this.numberDisplay.classList.add('zoom-animation');
|
| 91 |
+
break;
|
| 92 |
+
case 'bounce':
|
| 93 |
+
this.numberDisplay.classList.add('bounce-animation');
|
| 94 |
+
break;
|
| 95 |
+
case 'smoke':
|
| 96 |
+
this.numberDisplay.classList.add('smoke-animation');
|
| 97 |
+
this.createParticles();
|
| 98 |
+
break;
|
| 99 |
+
case 'glitch':
|
| 100 |
+
this.numberDisplay.classList.add('glitch-animation');
|
| 101 |
+
break;
|
| 102 |
+
case 'pulse':
|
| 103 |
+
this.numberDisplay.classList.add('pulse-animation');
|
| 104 |
+
break;
|
| 105 |
+
}
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
createParticles() {
|
| 109 |
+
// Clear existing particles
|
| 110 |
+
this.particlesContainer.innerHTML = '';
|
| 111 |
+
|
| 112 |
+
// Create new particles
|
| 113 |
+
for (let i = 0; i < 30; i++) {
|
| 114 |
+
const particle = document.createElement('div');
|
| 115 |
+
particle.classList.add('particle');
|
| 116 |
+
|
| 117 |
+
const angle = Math.random() * Math.PI * 2;
|
| 118 |
+
const distance = 100 + Math.random() * 200;
|
| 119 |
+
const tx = Math.cos(angle) * distance;
|
| 120 |
+
const ty = Math.sin(angle) * distance;
|
| 121 |
+
|
| 122 |
+
particle.style.setProperty('--tx', `${tx}px`);
|
| 123 |
+
particle.style.setProperty('--ty', `${ty}px`);
|
| 124 |
+
particle.style.left = '50%';
|
| 125 |
+
particle.style.top = '50%';
|
| 126 |
+
particle.style.animationDelay = `${Math.random() * 0.5}s`;
|
| 127 |
+
|
| 128 |
+
this.particlesContainer.appendChild(particle);
|
| 129 |
+
}
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
startAnimation() {
|
| 133 |
+
this.stopAnimation(); // Clear any existing timeout
|
| 134 |
+
|
| 135 |
+
if (this.isLooping && this.isPlaying) {
|
| 136 |
+
this.animationTimeout = setTimeout(() => {
|
| 137 |
+
this.changeNumber(1);
|
| 138 |
+
this.startAnimation();
|
| 139 |
+
}, 3000); // 3 second delay between numbers
|
| 140 |
+
}
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
stopAnimation() {
|
| 144 |
+
if (this.animationTimeout) {
|
| 145 |
+
clearTimeout(this.animationTimeout);
|
| 146 |
+
this.animationTimeout = null;
|
| 147 |
+
}
|
| 148 |
+
}
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
// Initialize the app when DOM is loaded
|
| 152 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 153 |
+
new CinematicNumbersApp();
|
| 154 |
+
});
|
| 155 |
+
|
| 156 |
+
// Handle feather icons replacement
|
| 157 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 158 |
+
if (typeof feather !== 'undefined') {
|
| 159 |
+
feather.replace();
|
| 160 |
+
}
|
| 161 |
+
});
|
style.css
CHANGED
|
@@ -1,28 +1,212 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
body {
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
}
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
margin-top: 0;
|
| 9 |
}
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
}
|
| 17 |
|
| 18 |
-
.
|
| 19 |
-
|
| 20 |
-
margin: 0 auto;
|
| 21 |
-
padding: 16px;
|
| 22 |
-
border: 1px solid lightgray;
|
| 23 |
-
border-radius: 16px;
|
| 24 |
}
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap');
|
| 2 |
+
|
| 3 |
+
* {
|
| 4 |
+
margin: 0;
|
| 5 |
+
padding: 0;
|
| 6 |
+
box-sizing: border-box;
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
body {
|
| 10 |
+
font-family: 'Bebas Neue', sans-serif;
|
| 11 |
+
background: #000;
|
| 12 |
+
color: white;
|
| 13 |
+
overflow: hidden;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
.cinematic-number {
|
| 17 |
+
font-family: 'Bebas Neue', sans-serif;
|
| 18 |
+
background: linear-gradient(145deg, #8b0000, #ff0000, #8b0000);
|
| 19 |
+
background-size: 200% 200%;
|
| 20 |
+
-webkit-background-clip: text;
|
| 21 |
+
background-clip: text;
|
| 22 |
+
-webkit-text-fill-color: transparent;
|
| 23 |
+
text-shadow:
|
| 24 |
+
0 0 30px rgba(255, 0, 0, 0.8),
|
| 25 |
+
0 0 60px rgba(255, 0, 0, 0.6),
|
| 26 |
+
0 0 90px rgba(255, 0, 0, 0.4),
|
| 27 |
+
2px 2px 4px rgba(0, 0, 0, 0.8),
|
| 28 |
+
-2px -2px 4px rgba(255, 255, 255, 0.1);
|
| 29 |
+
position: relative;
|
| 30 |
+
animation: shimmer 3s ease-in-out infinite;
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
.cinematic-number::before {
|
| 34 |
+
content: attr(data-number);
|
| 35 |
+
position: absolute;
|
| 36 |
+
top: 2px;
|
| 37 |
+
left: 2px;
|
| 38 |
+
background: linear-gradient(145deg, #2a2a2a, #1a1a1a);
|
| 39 |
+
-webkit-background-clip: text;
|
| 40 |
+
background-clip: text;
|
| 41 |
+
-webkit-text-fill-color: transparent;
|
| 42 |
+
z-index: -1;
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
.cinematic-number::after {
|
| 46 |
+
content: '';
|
| 47 |
+
position: absolute;
|
| 48 |
+
top: 0;
|
| 49 |
+
left: 0;
|
| 50 |
+
right: 0;
|
| 51 |
+
bottom: 0;
|
| 52 |
+
background: radial-gradient(circle at center, transparent 30%, rgba(255, 0, 0, 0.1) 100%);
|
| 53 |
+
border-radius: 10px;
|
| 54 |
+
z-index: -2;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
@keyframes shimmer {
|
| 58 |
+
0%, 100% {
|
| 59 |
+
background-position: 0% 50%;
|
| 60 |
+
filter: brightness(1);
|
| 61 |
+
}
|
| 62 |
+
50% {
|
| 63 |
+
background-position: 100% 50%;
|
| 64 |
+
filter: brightness(1.2);
|
| 65 |
+
}
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
/* Animation Classes */
|
| 69 |
+
.zoom-animation {
|
| 70 |
+
animation: zoomIn 2s ease-out;
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
@keyframes zoomIn {
|
| 74 |
+
0% {
|
| 75 |
+
transform: scale(0.1) rotate(-10deg);
|
| 76 |
+
opacity: 0;
|
| 77 |
+
filter: blur(20px);
|
| 78 |
+
}
|
| 79 |
+
60% {
|
| 80 |
+
transform: scale(1.1) rotate(2deg);
|
| 81 |
+
opacity: 1;
|
| 82 |
+
filter: blur(0);
|
| 83 |
+
}
|
| 84 |
+
100% {
|
| 85 |
+
transform: scale(1) rotate(0);
|
| 86 |
+
}
|
| 87 |
}
|
| 88 |
|
| 89 |
+
.bounce-animation {
|
| 90 |
+
animation: bounceIn 1.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
|
|
| 91 |
}
|
| 92 |
|
| 93 |
+
@keyframes bounceIn {
|
| 94 |
+
0% {
|
| 95 |
+
transform: scale(0.3);
|
| 96 |
+
opacity: 0;
|
| 97 |
+
}
|
| 98 |
+
50% {
|
| 99 |
+
transform: scale(1.05);
|
| 100 |
+
}
|
| 101 |
+
70% {
|
| 102 |
+
transform: scale(0.9);
|
| 103 |
+
}
|
| 104 |
+
100% {
|
| 105 |
+
transform: scale(1);
|
| 106 |
+
opacity: 1;
|
| 107 |
+
}
|
| 108 |
}
|
| 109 |
|
| 110 |
+
.smoke-animation {
|
| 111 |
+
animation: smokeReveal 2.5s ease-out;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
}
|
| 113 |
|
| 114 |
+
@keyframes smokeReveal {
|
| 115 |
+
0% {
|
| 116 |
+
transform: translateY(100px) scale(0.8);
|
| 117 |
+
opacity: 0;
|
| 118 |
+
filter: blur(30px);
|
| 119 |
+
}
|
| 120 |
+
50% {
|
| 121 |
+
transform: translateY(-20px) scale(1.1);
|
| 122 |
+
filter: blur(10px);
|
| 123 |
+
}
|
| 124 |
+
100% {
|
| 125 |
+
transform: translateY(0) scale(1);
|
| 126 |
+
opacity: 1;
|
| 127 |
+
filter: blur(0);
|
| 128 |
+
}
|
| 129 |
}
|
| 130 |
+
|
| 131 |
+
.glitch-animation {
|
| 132 |
+
animation: glitchFlicker 2s ease-out;
|
| 133 |
+
}
|
| 134 |
+
|
| 135 |
+
@keyframes glitchFlicker {
|
| 136 |
+
0%, 100% {
|
| 137 |
+
transform: translateX(0);
|
| 138 |
+
opacity: 1;
|
| 139 |
+
}
|
| 140 |
+
10%, 30%, 50%, 70%, 90% {
|
| 141 |
+
transform: translateX(-2px);
|
| 142 |
+
opacity: 0.8;
|
| 143 |
+
}
|
| 144 |
+
20%, 40%, 60%, 80% {
|
| 145 |
+
transform: translateX(2px);
|
| 146 |
+
opacity: 0.9;
|
| 147 |
+
}
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
.pulse-animation {
|
| 151 |
+
animation: energyPulse 2s ease-out;
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
@keyframes energyPulse {
|
| 155 |
+
0% {
|
| 156 |
+
transform: scale(0.5);
|
| 157 |
+
opacity: 0;
|
| 158 |
+
filter: brightness(0) blur(20px);
|
| 159 |
+
}
|
| 160 |
+
30% {
|
| 161 |
+
transform: scale(1.2);
|
| 162 |
+
filter: brightness(2) blur(5px);
|
| 163 |
+
}
|
| 164 |
+
50% {
|
| 165 |
+
transform: scale(0.9);
|
| 166 |
+
filter: brightness(1.5) blur(2px);
|
| 167 |
+
}
|
| 168 |
+
70% {
|
| 169 |
+
transform: scale(1.1);
|
| 170 |
+
filter: brightness(1.8) blur(1px);
|
| 171 |
+
}
|
| 172 |
+
100% {
|
| 173 |
+
transform: scale(1);
|
| 174 |
+
opacity: 1;
|
| 175 |
+
filter: brightness(1) blur(0);
|
| 176 |
+
}
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
/* Particle Effects */
|
| 180 |
+
.particle {
|
| 181 |
+
position: absolute;
|
| 182 |
+
width: 4px;
|
| 183 |
+
height: 4px;
|
| 184 |
+
background: #ff0000;
|
| 185 |
+
border-radius: 50%;
|
| 186 |
+
pointer-events: none;
|
| 187 |
+
animation: particleFloat 2s ease-out forwards;
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
@keyframes particleFloat {
|
| 191 |
+
0% {
|
| 192 |
+
transform: translate(0, 0) scale(1);
|
| 193 |
+
opacity: 1;
|
| 194 |
+
}
|
| 195 |
+
100% {
|
| 196 |
+
transform: translate(var(--tx), var(--ty)) scale(0);
|
| 197 |
+
opacity: 0;
|
| 198 |
+
}
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
/* Responsive adjustments */
|
| 202 |
+
@media (max-width: 768px) {
|
| 203 |
+
.cinematic-number {
|
| 204 |
+
font-size: 12rem !important;
|
| 205 |
+
}
|
| 206 |
+
}
|
| 207 |
+
|
| 208 |
+
@media (max-width: 480px) {
|
| 209 |
+
.cinematic-number {
|
| 210 |
+
font-size: 8rem !important;
|
| 211 |
+
}
|
| 212 |
+
}
|