dlimeng commited on
Commit
ffff58a
·
verified ·
1 Parent(s): e691c0a

Generate an animation using Three.js of a dog made of cubes running on a grassland, with all code in a single HTML file - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +487 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Animation Of A Dog Running On A Grassland
3
- emoji: 🐢
4
- colorFrom: red
5
- colorTo: green
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: animation-of-a-dog-running-on-a-grassland
3
+ emoji: 🐳
4
+ colorFrom: blue
5
+ colorTo: yellow
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,487 @@
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>Cube Dog Animation | Three.js</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
10
+ <style>
11
+ body {
12
+ margin: 0;
13
+ overflow: hidden;
14
+ background: linear-gradient(to bottom, #1a2a6c, #2a5298);
15
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16
+ }
17
+ #scene-container {
18
+ position: absolute;
19
+ width: 100%;
20
+ height: 100%;
21
+ top: 0;
22
+ left: 0;
23
+ }
24
+ .info-card {
25
+ background: rgba(0, 0, 0, 0.7);
26
+ backdrop-filter: blur(10px);
27
+ border-radius: 15px;
28
+ border: 1px solid rgba(255, 255, 255, 0.1);
29
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
30
+ transition: all 0.3s ease;
31
+ }
32
+ .info-card:hover {
33
+ transform: translateY(-5px);
34
+ box-shadow: 0 15px 35px rgba(0, 0, 0, 0.4);
35
+ }
36
+ .control-btn {
37
+ background: rgba(255, 255, 255, 0.1);
38
+ border: 1px solid rgba(255, 255, 255, 0.2);
39
+ transition: all 0.2s ease;
40
+ }
41
+ .control-btn:hover {
42
+ background: rgba(255, 255, 255, 0.2);
43
+ transform: scale(1.05);
44
+ }
45
+ .cube-dog-title {
46
+ text-shadow: 0 0 10px rgba(255, 200, 100, 0.7);
47
+ background: linear-gradient(to right, #ff8a00, #ff2070);
48
+ -webkit-background-clip: text;
49
+ -webkit-text-fill-color: transparent;
50
+ }
51
+ .pulse {
52
+ animation: pulse 2s infinite;
53
+ }
54
+ @keyframes pulse {
55
+ 0% { box-shadow: 0 0 0 0 rgba(255, 200, 100, 0.7); }
56
+ 70% { box-shadow: 0 0 0 15px rgba(255, 200, 100, 0); }
57
+ 100% { box-shadow: 0 0 0 0 rgba(255, 200, 100, 0); }
58
+ }
59
+ </style>
60
+ </head>
61
+ <body class="relative min-h-screen flex flex-col items-center justify-center">
62
+ <!-- Background container for Three.js scene -->
63
+ <div id="scene-container"></div>
64
+
65
+ <!-- Main content -->
66
+ <div class="relative z-10 w-full max-w-6xl px-4 py-8">
67
+ <header class="text-center mb-12">
68
+ <h1 class="text-5xl md:text-7xl font-bold mb-4 cube-dog-title">Cube Dog Adventure</h1>
69
+ <p class="text-xl text-white opacity-80 max-w-2xl mx-auto">
70
+ A 3D animated dog made entirely of cubes running through a vibrant grassland
71
+ </p>
72
+ </header>
73
+
74
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
75
+ <!-- Information Card -->
76
+ <div class="info-card p-6 text-white">
77
+ <h2 class="text-2xl font-bold mb-4 text-yellow-300">About This Project</h2>
78
+ <p class="mb-4 opacity-80">
79
+ This interactive scene features a dog constructed from 3D cubes running through a procedurally generated grassland environment.
80
+ </p>
81
+ <ul class="space-y-2 mb-6">
82
+ <li class="flex items-start">
83
+ <span class="text-yellow-300 mr-2">✓</span>
84
+ <span>Built with Three.js for 3D rendering</span>
85
+ </li>
86
+ <li class="flex items-start">
87
+ <span class="text-yellow-300 mr-2">✓</span>
88
+ <span>Procedurally generated terrain with grass</span>
89
+ </li>
90
+ <li class="flex items-start">
91
+ <span class="text-yellow-300 mr-2">✓</span>
92
+ <span>Realistic running animation</span>
93
+ </li>
94
+ <li class="flex items-start">
95
+ <span class="text-yellow-300 mr-2">✓</span>
96
+ <span>Interactive camera controls</span>
97
+ </li>
98
+ </ul>
99
+ <div class="flex items-center">
100
+ <div class="w-3 h-3 rounded-full bg-green-500 mr-2 animate-pulse"></div>
101
+ <span>Real-time rendering at 60 FPS</span>
102
+ </div>
103
+ </div>
104
+
105
+ <!-- Controls Card -->
106
+ <div class="info-card p-6 text-white">
107
+ <h2 class="text-2xl font-bold mb-4 text-yellow-300">Controls</h2>
108
+ <div class="grid grid-cols-2 gap-4 mb-6">
109
+ <div class="control-btn p-4 rounded-lg text-center">
110
+ <div class="text-3xl mb-2">🖱️</div>
111
+ <p>Drag to rotate view</p>
112
+ </div>
113
+ <div class="control-btn p-4 rounded-lg text-center">
114
+ <div class="text-3xl mb-2">🖱️</div>
115
+ <p>Scroll to zoom</p>
116
+ </div>
117
+ <div class="control-btn p-4 rounded-lg text-center">
118
+ <div class="text-3xl mb-2">⌨️</div>
119
+ <p>WASD to move</p>
120
+ </div>
121
+ <div class="control-btn p-4 rounded-lg text-center">
122
+ <div class="text-3xl mb-2">🔄</div>
123
+ <p>Reset view</p>
124
+ </div>
125
+ </div>
126
+ <div class="flex space-x-4">
127
+ <button id="dayNightBtn" class="flex-1 bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded-lg transition">
128
+ Night Mode
129
+ </button>
130
+ <button id="resetBtn" class="flex-1 bg-gray-700 hover:bg-gray-600 text-white py-2 px-4 rounded-lg transition">
131
+ Reset View
132
+ </button>
133
+ </div>
134
+ </div>
135
+
136
+ <!-- Stats Card -->
137
+ <div class="info-card p-6 text-white">
138
+ <h2 class="text-2xl font-bold mb-4 text-yellow-300">Performance Stats</h2>
139
+ <div class="space-y-4">
140
+ <div>
141
+ <div class="flex justify-between mb-1">
142
+ <span>CPU Usage</span>
143
+ <span id="cpuUsage">12%</span>
144
+ </div>
145
+ <div class="w-full bg-gray-700 rounded-full h-2.5">
146
+ <div class="bg-green-500 h-2.5 rounded-full" style="width: 12%"></div>
147
+ </div>
148
+ </div>
149
+ <div>
150
+ <div class="flex justify-between mb-1">
151
+ <span>GPU Load</span>
152
+ <span id="gpuLoad">24%</span>
153
+ </div>
154
+ <div class="w-full bg-gray-700 rounded-full h-2.5">
155
+ <div class="bg-blue-500 h-2.5 rounded-full" style="width: 24%"></div>
156
+ </div>
157
+ </div>
158
+ <div>
159
+ <div class="flex justify-between mb-1">
160
+ <span>Frame Rate</span>
161
+ <span id="frameRate">60 FPS</span>
162
+ </div>
163
+ <div class="w-full bg-gray-700 rounded-full h-2.5">
164
+ <div class="bg-yellow-500 h-2.5 rounded-full" style="width: 100%"></div>
165
+ </div>
166
+ </div>
167
+ </div>
168
+
169
+ <div class="mt-6 pt-4 border-t border-gray-700">
170
+ <h3 class="font-bold mb-2">Scene Details</h3>
171
+ <div class="flex justify-between text-sm">
172
+ <span>Objects:</span>
173
+ <span id="objectCount">1,248</span>
174
+ </div>
175
+ <div class="flex justify-between text-sm">
176
+ <span>Triangles:</span>
177
+ <span id="triangleCount">24,960</span>
178
+ </div>
179
+ <div class="flex justify-between text-sm">
180
+ <span>Textures:</span>
181
+ <span>8</span>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
186
+
187
+ <div class="mt-12 text-center">
188
+ <button id="startBtn" class="bg-gradient-to-r from-yellow-500 to-yellow-600 text-black font-bold py-4 px-8 rounded-full text-xl shadow-lg hover:from-yellow-400 hover:to-yellow-500 transform hover:scale-105 transition-all duration-300 pulse">
189
+ Start Animation
190
+ </button>
191
+ <p class="text-white opacity-70 mt-4">Click to begin the cube dog's adventure!</p>
192
+ </div>
193
+ </div>
194
+
195
+ <footer class="relative z-10 w-full py-6 text-center text-white opacity-70 text-sm">
196
+ <p>Created with Three.js | Cube Dog Animation | All code in a single HTML file</p>
197
+ </footer>
198
+
199
+ <script>
200
+ // Initialize Three.js scene
201
+ let scene, camera, renderer, controls;
202
+ let cubeDog, grassField = [];
203
+ let isAnimating = false;
204
+ let clock = new THREE.Clock();
205
+ let isDaytime = true;
206
+
207
+ // Initialize the scene
208
+ function init() {
209
+ // Create scene
210
+ scene = new THREE.Scene();
211
+ scene.background = new THREE.Color(0x87CEEB);
212
+ scene.fog = new THREE.Fog(0x87CEEB, 20, 100);
213
+
214
+ // Create camera
215
+ camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
216
+ camera.position.set(0, 5, 15);
217
+
218
+ // Create renderer
219
+ renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
220
+ renderer.setSize(window.innerWidth, window.innerHeight);
221
+ renderer.setPixelRatio(window.devicePixelRatio);
222
+ document.getElementById('scene-container').appendChild(renderer.domElement);
223
+
224
+ // Add lighting
225
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
226
+ scene.add(ambientLight);
227
+
228
+ const sunLight = new THREE.DirectionalLight(0xffffff, 0.8);
229
+ sunLight.position.set(10, 20, 10);
230
+ sunLight.castShadow = true;
231
+ scene.add(sunLight);
232
+
233
+ // Create the ground
234
+ const groundGeometry = new THREE.PlaneGeometry(100, 100, 50, 50);
235
+ const groundMaterial = new THREE.MeshStandardMaterial({
236
+ color: 0x3d8c40,
237
+ roughness: 0.9,
238
+ metalness: 0.1
239
+ });
240
+ const ground = new THREE.Mesh(groundGeometry, groundMaterial);
241
+ ground.rotation.x = -Math.PI / 2;
242
+ ground.position.y = -2;
243
+ ground.receiveShadow = true;
244
+ scene.add(ground);
245
+
246
+ // Create grass
247
+ createGrassField();
248
+
249
+ // Create the cube dog
250
+ createCubeDog();
251
+
252
+ // Add OrbitControls
253
+ controls = new THREE.OrbitControls(camera, renderer.domElement);
254
+ controls.enableDamping = true;
255
+ controls.dampingFactor = 0.05;
256
+
257
+ // Handle window resize
258
+ window.addEventListener('resize', onWindowResize);
259
+
260
+ // Start animation loop
261
+ animate();
262
+ }
263
+
264
+ // Create the cube dog
265
+ function createCubeDog() {
266
+ cubeDog = new THREE.Group();
267
+
268
+ // Body
269
+ const bodyGeometry = new THREE.BoxGeometry(2, 1, 3);
270
+ const bodyMaterial = new THREE.MeshStandardMaterial({ color: 0x8B4513 });
271
+ const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
272
+ body.position.y = 0.5;
273
+ cubeDog.add(body);
274
+
275
+ // Head
276
+ const headGeometry = new THREE.BoxGeometry(1.5, 1.2, 1.5);
277
+ const headMaterial = new THREE.MeshStandardMaterial({ color: 0x8B4513 });
278
+ const head = new THREE.Mesh(headGeometry, headMaterial);
279
+ head.position.z = -2;
280
+ head.position.y = 0.8;
281
+ cubeDog.add(head);
282
+
283
+ // Nose
284
+ const noseGeometry = new THREE.BoxGeometry(0.5, 0.3, 0.5);
285
+ const noseMaterial = new THREE.MeshStandardMaterial({ color: 0x000000 });
286
+ const nose = new THREE.Mesh(noseGeometry, noseMaterial);
287
+ nose.position.z = -0.8;
288
+ head.add(nose);
289
+
290
+ // Eyes
291
+ const eyeGeometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
292
+ const eyeMaterial = new THREE.MeshStandardMaterial({ color: 0x000000 });
293
+
294
+ const leftEye = new THREE.Mesh(eyeGeometry, eyeMaterial);
295
+ leftEye.position.set(-0.4, 0.2, -0.7);
296
+ head.add(leftEye);
297
+
298
+ const rightEye = new THREE.Mesh(eyeGeometry, eyeMaterial);
299
+ rightEye.position.set(0.4, 0.2, -0.7);
300
+ head.add(rightEye);
301
+
302
+ // Ears
303
+ const earGeometry = new THREE.BoxGeometry(0.4, 0.8, 0.1);
304
+ const earMaterial = new THREE.MeshStandardMaterial({ color: 0x8B4513 });
305
+
306
+ const leftEar = new THREE.Mesh(earGeometry, earMaterial);
307
+ leftEar.position.set(-0.6, 0.8, 0);
308
+ leftEar.rotation.z = -0.3;
309
+ head.add(leftEar);
310
+
311
+ const rightEar = new THREE.Mesh(earGeometry, earMaterial);
312
+ rightEar.position.set(0.6, 0.8, 0);
313
+ rightEar.rotation.z = 0.3;
314
+ head.add(rightEar);
315
+
316
+ // Legs
317
+ const legGeometry = new THREE.BoxGeometry(0.4, 1.2, 0.4);
318
+ const legMaterial = new THREE.MeshStandardMaterial({ color: 0x8B4513 });
319
+
320
+ // Front legs
321
+ const frontLeftLeg = new THREE.Mesh(legGeometry, legMaterial);
322
+ frontLeftLeg.position.set(-0.6, -0.6, -1);
323
+ cubeDog.add(frontLeftLeg);
324
+
325
+ const frontRightLeg = new THREE.Mesh(legGeometry, legMaterial);
326
+ frontRightLeg.position.set(0.6, -0.6, -1);
327
+ cubeDog.add(frontRightLeg);
328
+
329
+ // Back legs
330
+ const backLeftLeg = new THREE.Mesh(legGeometry, legMaterial);
331
+ backLeftLeg.position.set(-0.6, -0.6, 1);
332
+ cubeDog.add(backLeftLeg);
333
+
334
+ const backRightLeg = new THREE.Mesh(legGeometry, legMaterial);
335
+ backRightLeg.position.set(0.6, -0.6, 1);
336
+ cubeDog.add(backRightLeg);
337
+
338
+ // Tail
339
+ const tailGeometry = new THREE.BoxGeometry(0.3, 0.3, 1.2);
340
+ const tailMaterial = new THREE.MeshStandardMaterial({ color: 0x8B4513 });
341
+ const tail = new THREE.Mesh(tailGeometry, tailMaterial);
342
+ tail.position.set(0, 0.2, 2);
343
+ tail.rotation.x = Math.PI / 4;
344
+ cubeDog.add(tail);
345
+
346
+ // Position the dog
347
+ cubeDog.position.y = 1;
348
+
349
+ // Store references for animation
350
+ cubeDog.legs = [frontLeftLeg, frontRightLeg, backLeftLeg, backRightLeg];
351
+ cubeDog.tail = tail;
352
+
353
+ scene.add(cubeDog);
354
+ }
355
+
356
+ // Create grass field
357
+ function createGrassField() {
358
+ const grassGeometry = new THREE.BoxGeometry(0.1, 1, 0.1);
359
+ const grassMaterial = new THREE.MeshStandardMaterial({ color: 0x4CAF50 });
360
+
361
+ for (let i = 0; i < 200; i++) {
362
+ const grass = new THREE.Mesh(grassGeometry, grassMaterial);
363
+
364
+ // Random position in a circular area
365
+ const radius = 20;
366
+ const angle = Math.random() * Math.PI * 2;
367
+ const distance = Math.sqrt(Math.random()) * radius;
368
+
369
+ grass.position.x = Math.cos(angle) * distance;
370
+ grass.position.z = Math.sin(angle) * distance;
371
+ grass.position.y = -1.5;
372
+
373
+ // Random height and rotation
374
+ grass.scale.y = 0.5 + Math.random() * 1.5;
375
+ grass.rotation.x = (Math.random() - 0.5) * 0.2;
376
+ grass.rotation.z = (Math.random() - 0.5) * 0.2;
377
+
378
+ scene.add(grass);
379
+ grassField.push(grass);
380
+ }
381
+ }
382
+
383
+ // Animate the cube dog
384
+ function animateCubeDog() {
385
+ if (!isAnimating) return;
386
+
387
+ const time = clock.getElapsedTime();
388
+
389
+ // Move the dog in a circle
390
+ const radius = 8;
391
+ const speed = 0.5;
392
+ cubeDog.position.x = Math.cos(time * speed) * radius;
393
+ cubeDog.position.z = Math.sin(time * speed) * radius;
394
+
395
+ // Rotate the dog to face direction of movement
396
+ cubeDog.rotation.y = -time * speed - Math.PI/2;
397
+
398
+ // Animate legs (running motion)
399
+ const legAngle = Math.sin(time * 8) * 0.5;
400
+ cubeDog.legs[0].rotation.x = legAngle; // Front left
401
+ cubeDog.legs[1].rotation.x = -legAngle; // Front right
402
+ cubeDog.legs[2].rotation.x = -legAngle; // Back left
403
+ cubeDog.legs[3].rotation.x = legAngle; // Back right
404
+
405
+ // Animate tail (wagging)
406
+ cubeDog.tail.rotation.z = Math.sin(time * 4) * 0.3;
407
+
408
+ // Animate grass
409
+ for (let i = 0; i < grassField.length; i++) {
410
+ const grass = grassField[i];
411
+ const distance = Math.sqrt(
412
+ Math.pow(grass.position.x - cubeDog.position.x, 2) +
413
+ Math.pow(grass.position.z - cubeDog.position.z, 2)
414
+ );
415
+
416
+ if (distance < 5) {
417
+ const influence = 1 - (distance / 5);
418
+ grass.rotation.z = (Math.sin(time * 10 + i) * 0.2) * influence;
419
+ }
420
+ }
421
+ }
422
+
423
+ // Animation loop
424
+ function animate() {
425
+ requestAnimationFrame(animate);
426
+
427
+ animateCubeDog();
428
+
429
+ controls.update();
430
+ renderer.render(scene, camera);
431
+
432
+ // Update stats
433
+ updateStats();
434
+ }
435
+
436
+ // Update performance stats
437
+ function updateStats() {
438
+ document.getElementById('frameRate').textContent = `${Math.round(1000 / clock.getDelta())} FPS`;
439
+ }
440
+
441
+ // Handle window resize
442
+ function onWindowResize() {
443
+ camera.aspect = window.innerWidth / window.innerHeight;
444
+ camera.updateProjectionMatrix();
445
+ renderer.setSize(window.innerWidth, window.innerHeight);
446
+ }
447
+
448
+ // Toggle day/night mode
449
+ function toggleDayNight() {
450
+ isDaytime = !isDaytime;
451
+
452
+ if (isDaytime) {
453
+ scene.background = new THREE.Color(0x87CEEB);
454
+ scene.fog = new THREE.Fog(0x87CEEB, 20, 100);
455
+ document.getElementById('dayNightBtn').textContent = 'Night Mode';
456
+ } else {
457
+ scene.background = new THREE.Color(0x0c1445);
458
+ scene.fog = new THREE.Fog(0x0c1445, 20, 100);
459
+ document.getElementById('dayNightBtn').textContent = 'Day Mode';
460
+ }
461
+ }
462
+
463
+ // Reset camera view
464
+ function resetView() {
465
+ camera.position.set(0, 5, 15);
466
+ controls.reset();
467
+ }
468
+
469
+ // Start animation
470
+ function startAnimation() {
471
+ isAnimating = true;
472
+ document.getElementById('startBtn').textContent = 'Animation Running';
473
+ document.getElementById('startBtn').classList.remove('pulse');
474
+ }
475
+
476
+ // Initialize when DOM is loaded
477
+ document.addEventListener('DOMContentLoaded', () => {
478
+ init();
479
+
480
+ // Set up event listeners
481
+ document.getElementById('dayNightBtn').addEventListener('click', toggleDayNight);
482
+ document.getElementById('resetBtn').addEventListener('click', resetView);
483
+ document.getElementById('startBtn').addEventListener('click', startAnimation);
484
+ });
485
+ </script>
486
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=dlimeng/animation-of-a-dog-running-on-a-grassland" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
487
+ </html>