ivanfioravanti commited on
Commit
24bc5c4
·
verified ·
1 Parent(s): 97185fe

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. assets/css/styles.css +67 -0
  2. assets/js/particles.js +264 -0
  3. index.html +27 -19
assets/css/styles.css ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * {
2
+ margin: 0;
3
+ padding: 0;
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ body {
8
+ background: #0a0a0a;
9
+ overflow: hidden;
10
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
11
+ }
12
+
13
+ #particleCanvas {
14
+ display: block;
15
+ cursor: crosshair;
16
+ }
17
+
18
+ .controls {
19
+ position: fixed;
20
+ top: 20px;
21
+ left: 20px;
22
+ color: #ffffff;
23
+ background: rgba(0, 0, 0, 0.7);
24
+ padding: 20px;
25
+ border-radius: 10px;
26
+ backdrop-filter: blur(10px);
27
+ border: 1px solid rgba(255, 255, 255, 0.1);
28
+ max-width: 300px;
29
+ transition: opacity 0.3s ease;
30
+ }
31
+
32
+ .controls:hover {
33
+ opacity: 0.9;
34
+ }
35
+
36
+ .control-info h2 {
37
+ font-size: 1.2rem;
38
+ margin-bottom: 15px;
39
+ color: #64ffda;
40
+ }
41
+
42
+ .control-info p {
43
+ font-size: 0.9rem;
44
+ margin-bottom: 8px;
45
+ line-height: 1.4;
46
+ }
47
+
48
+ .control-info strong {
49
+ color: #64ffda;
50
+ }
51
+
52
+ @media (max-width: 768px) {
53
+ .controls {
54
+ top: 10px;
55
+ left: 10px;
56
+ padding: 15px;
57
+ max-width: 250px;
58
+ }
59
+
60
+ .control-info h2 {
61
+ font-size: 1rem;
62
+ }
63
+
64
+ .control-info p {
65
+ font-size: 0.8rem;
66
+ }
67
+ }
assets/js/particles.js ADDED
@@ -0,0 +1,264 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const canvas = document.getElementById('particleCanvas');
2
+ const ctx = canvas.getContext('2d');
3
+
4
+ canvas.width = window.innerWidth;
5
+ canvas.height = window.innerHeight;
6
+
7
+ // Configuration
8
+ let config = {
9
+ particleCount: 100,
10
+ particleSize: 2,
11
+ speed: 1,
12
+ connectionDistance: 100,
13
+ colorMode: 'rainbow',
14
+ mouseEffect: 'attract',
15
+ mouseRadius: 150
16
+ };
17
+
18
+ // Mouse position
19
+ let mouse = {
20
+ x: canvas.width / 2,
21
+ y: canvas.height / 2
22
+ };
23
+
24
+ // Particles array
25
+ let particles = [];
26
+
27
+ // Color modes
28
+ const colorModes = {
29
+ rainbow: (particle, time) => {
30
+ const hue = (time * 0.1 + particle.id * 10) % 360;
31
+ return `hsl(${hue}, 70%, 50%)`;
32
+ },
33
+ ocean: (particle, time) => {
34
+ const hue = 180 + Math.sin(time * 0.001 + particle.id * 0.1) * 60;
35
+ return `hsl(${hue}, 70%, 50%)`;
36
+ },
37
+ fire: (particle, time) => {
38
+ const hue = Math.sin(time * 0.001 + particle.id * 0.1) * 30;
39
+ return `hsl(${hue}, 80%, 50%)`;
40
+ },
41
+ monochrome: (particle, time) => {
42
+ const brightness = 30 + Math.sin(time * 0.001 + particle.id * 0.1) * 20;
43
+ return `hsl(0, 0%, ${brightness}%)`;
44
+ },
45
+ neon: (particle, time) => {
46
+ const colors = ['#ff00ff', '#00ffff', '#ffff00', '#ff00aa'];
47
+ return colors[Math.floor((time * 0.001 + particle.id * 0.1) % colors.length)];
48
+ }
49
+ };
50
+
51
+ // Particle class
52
+ class Particle {
53
+ constructor(id) {
54
+ this.id = id;
55
+ this.x = Math.random() * canvas.width;
56
+ this.y = Math.random() * canvas.height;
57
+ this.vx = (Math.random() - 0.5) * config.speed;
58
+ this.vy = (Math.random() - 0.5) * config.speed;
59
+ this.size = config.particleSize;
60
+ this.baseSize = config.particleSize;
61
+ }
62
+
63
+ update() {
64
+ // Mouse interaction
65
+ const dx = mouse.x - this.x;
66
+ const dy = mouse.y - this.y;
67
+ const distance = Math.sqrt(dx * dx + dy * dy);
68
+
69
+ if (distance < config.mouseRadius) {
70
+ const force = (1 - distance / config.mouseRadius) * 0.5;
71
+ if (config.mouseEffect === 'attract') {
72
+ this.vx += dx * force * 0.01;
73
+ this.vy += dy * force * 0.01;
74
+ } else {
75
+ this.vx -= dx * force * 0.01;
76
+ this.vy -= dy * force * 0.01;
77
+ }
78
+ }
79
+
80
+ // Update position
81
+ this.x += this.vx * config.speed;
82
+ this.y += this.vy * config.speed;
83
+
84
+ // Bounce off walls
85
+ if (this.x < 0 || this.x > canvas.width) {
86
+ this.vx *= -0.9;
87
+ this.x = Math.max(0, Math.min(canvas.width, this.x));
88
+ }
89
+ if (this.y < 0 || this.y > canvas.height) {
90
+ this.vy *= -0.9;
91
+ this.y = Math.max(0, Math.min(canvas.height, this.y));
92
+ }
93
+
94
+ // Apply friction
95
+ this.vx *= 0.99;
96
+ this.vy *= 0.99;
97
+
98
+ // Size animation
99
+ this.size = this.baseSize + Math.sin(Date.now() * 0.001 + this.id) * 0.5;
100
+ }
101
+
102
+ draw(time) {
103
+ ctx.fillStyle = colorModes[config.colorMode](this, time);
104
+ ctx.beginPath();
105
+ ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
106
+ ctx.fill();
107
+
108
+ // Glow effect
109
+ ctx.shadowBlur = 10;
110
+ ctx.shadowColor = colorModes[config.colorMode](this, time);
111
+ ctx.fill();
112
+ ctx.shadowBlur = 0;
113
+ }
114
+ }
115
+
116
+ // Initialize particles
117
+ function initParticles() {
118
+ particles = [];
119
+ for (let i = 0; i < config.particleCount; i++) {
120
+ particles.push(new Particle(i));
121
+ }
122
+ }
123
+
124
+ // Draw connections between particles
125
+ function drawConnections() {
126
+ for (let i = 0; i < particles.length; i++) {
127
+ for (let j = i + 1; j < particles.length; j++) {
128
+ const dx = particles[i].x - particles[j].x;
129
+ const dy = particles[i].y - particles[j].y;
130
+ const distance = Math.sqrt(dx * dx + dy * dy);
131
+
132
+ if (distance < config.connectionDistance) {
133
+ const opacity = 1 - distance / config.connectionDistance;
134
+ ctx.strokeStyle = `rgba(100, 255, 218, ${opacity * 0.2})`;
135
+ ctx.lineWidth = opacity * 0.5;
136
+ ctx.beginPath();
137
+ ctx.moveTo(particles[i].x, particles[i].y);
138
+ ctx.lineTo(particles[j].x, particles[j].y);
139
+ ctx.stroke();
140
+ }
141
+ }
142
+ }
143
+ }
144
+
145
+ // Animation loop
146
+ function animate() {
147
+ ctx.fillStyle = 'rgba(10, 10, 10, 0.1)';
148
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
149
+
150
+ const time = Date.now();
151
+
152
+ // Update and draw particles
153
+ particles.forEach(particle => {
154
+ particle.update();
155
+ particle.draw(time);
156
+ });
157
+
158
+ // Draw connections
159
+ drawConnections();
160
+
161
+ requestAnimationFrame(animate);
162
+ }
163
+
164
+ // Event listeners
165
+ window.addEventListener('resize', () => {
166
+ canvas.width = window.innerWidth;
167
+ canvas.height = window.innerHeight;
168
+ });
169
+
170
+ canvas.addEventListener('mousemove', (e) => {
171
+ mouse.x = e.clientX;
172
+ mouse.y = e.clientY;
173
+ });
174
+
175
+ canvas.addEventListener('click', (e) => {
176
+ // Create explosion effect
177
+ for (let i = 0; i < 20; i++) {
178
+ const angle = (Math.PI * 2 * i) / 20;
179
+ const speed = 5 + Math.random() * 5;
180
+ const particle = new Particle(particles.length);
181
+ particle.x = e.clientX;
182
+ particle.y = e.clientY;
183
+ particle.vx = Math.cos(angle) * speed;
184
+ particle.vy = Math.sin(angle) * speed;
185
+ particle.baseSize = 3 + Math.random() * 2;
186
+ particles.push(particle);
187
+ }
188
+
189
+ // Remove excess particles
190
+ if (particles.length > config.particleCount * 2) {
191
+ particles.splice(0, particles.length - config.particleCount);
192
+ }
193
+ });
194
+
195
+ // Keyboard controls
196
+ document.addEventListener('keydown', (e) => {
197
+ switch(e.key.toLowerCase()) {
198
+ case ' ':
199
+ e.preventDefault();
200
+ const modes = Object.keys(colorModes);
201
+ const currentIndex = modes.indexOf(config.colorMode);
202
+ config.colorMode = modes[(currentIndex + 1) % modes.length];
203
+ break;
204
+ case '1':
205
+ config.particleCount = 50;
206
+ initParticles();
207
+ break;
208
+ case '2':
209
+ config.particleCount = 100;
210
+ initParticles();
211
+ break;
212
+ case '3':
213
+ config.particleCount = 200;
214
+ initParticles();
215
+ break;
216
+ case '4':
217
+ config.particleCount = 300;
218
+ initParticles();
219
+ break;
220
+ case '5':
221
+ config.particleCount = 500;
222
+ initParticles();
223
+ break;
224
+ case 'q':
225
+ config.speed = Math.max(0.1, config.speed - 0.1);
226
+ break;
227
+ case 'w':
228
+ config.speed = Math.min(5, config.speed + 0.1);
229
+ break;
230
+ case 'a':
231
+ config.particleSize = Math.max(1, config.particleSize - 0.5);
232
+ particles.forEach(p => p.baseSize = config.particleSize);
233
+ break;
234
+ case 's':
235
+ config.particleSize = Math.min(10, config.particleSize + 0.5);
236
+ particles.forEach(p => p.baseSize = config.particleSize);
237
+ break;
238
+ case 'z':
239
+ config.connectionDistance = Math.max(50, config.connectionDistance - 10);
240
+ break;
241
+ case 'x':
242
+ config.connectionDistance = Math.min(300, config.connectionDistance + 10);
243
+ break;
244
+ case 'r':
245
+ config = {
246
+ particleCount: 100,
247
+ particleSize: 2,
248
+ speed: 1,
249
+ connectionDistance: 100,
250
+ colorMode: 'rainbow',
251
+ mouseEffect: 'attract',
252
+ mouseRadius: 150
253
+ };
254
+ initParticles();
255
+ break;
256
+ case 'm':
257
+ config.mouseEffect = config.mouseEffect === 'attract' ? 'repel' : 'attract';
258
+ break;
259
+ }
260
+ });
261
+
262
+ // Initialize and start
263
+ initParticles();
264
+ animate();
index.html CHANGED
@@ -1,19 +1,27 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
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>Interactive Particle Animation</title>
7
+ <meta name="description" content="Beautiful interactive particle animation with keyboard and mouse controls">
8
+ <link rel="stylesheet" href="assets/css/styles.css">
9
+ </head>
10
+ <body>
11
+ <canvas id="particleCanvas"></canvas>
12
+ <div class="controls">
13
+ <div class="control-info">
14
+ <h2>Controls</h2>
15
+ <p><strong>Mouse:</strong> Move to attract/repel particles</p>
16
+ <p><strong>Click:</strong> Create particle explosion</p>
17
+ <p><strong>Space:</strong> Toggle color mode</p>
18
+ <p><strong>1-5:</strong> Change particle count</p>
19
+ <p><strong>Q/W:</strong> Decrease/Increase speed</p>
20
+ <p><strong>A/S:</strong> Decrease/Increase size</p>
21
+ <p><strong>Z/X:</strong> Decrease/Increase connection distance</p>
22
+ <p><strong>R:</strong> Reset to defaults</p>
23
+ </div>
24
+ </div>
25
+ <script src="assets/js/particles.js"></script>
26
+ </body>
27
+ </html>