HTML/JS animace
Vytvoření interaktivní 3D particle animace pomocí HTML, CSS a JavaScriptu.
Prompt
Create an interactive 3D particle animation using HTML, CSS and JavaScript (using Three.js from CDN). The animation should: display 5000 colorful particles rotating in a galaxy-like spiral, respond to mouse movement (tilt), have a starfield background, and show FPS counter in the corner. Make it visually impressive with smooth animations. Include everything in a single HTML file.
Výsledky napříč modely
| Model | Run | Tokens/s | Délka (s) | Tokeny | GPU VRAM | Processor | OK | Kvalita | Datum | Výstup |
|---|---|---|---|---|---|---|---|---|---|---|
| qwen3:32b-q4_K_M | #1 | 8.19 | 671.5 | 4096 | 4565 MB | 8%/92% CPU/GPU | ✅ | - | 12.08.2026 | — |
| qwen3-coder:30b | #1 | 86.49 | 75.1 | 2447 | 4021 MB | 1%/99% CPU/GPU | ✅ | - | 12.08.2026 | |
| qwen3:32b-q4_K_M | #1 | 9.20 | 670.7 | 4096 | 4565 MB | 7%/93% CPU/GPU | ✅ | - | 08.08.2026 | — |
| qwen3-coder:30b | #1 | 87.41 | 30.7 | 2643 | 3633 MB | 1%/99% CPU/GPU | ✅ | - | 08.08.2026 | |
| gemma4:e4b | #1 | 86.77 | 30.2 | 2568 | 15 MB | 100% GPU | ✅ | - | 08.08.2026 | |
| qwen3-coder:30b | #1 | 41.85 | 56.8 | 2332 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 07.08.2026 | |
| gemma4:e4b | #1 | 87.23 | 28.3 | 2420 | 3877 MB | 100% GPU | ✅ | - | 07.08.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.41 | 986.7 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 06.08.2026 | — |
| qwen3-coder:30b | #1 | 49.88 | 52.1 | 2565 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 06.08.2026 | |
| gemma4:e4b | #1 | 86.21 | 29.6 | 2500 | 3877 MB | 100% GPU | ✅ | - | 06.08.2026 | |
| qwen3-coder:30b | #1 | 40.23 | 137.2 | 2909 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 05.08.2026 | |
| gemma4:e4b | #1 | 85.06 | 51.7 | 2592 | 3877 MB | 100% GPU | ✅ | - | 05.08.2026 | |
| qwen3-coder:30b | #1 | 40.41 | 54.0 | 2154 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 04.08.2026 | |
| gemma4:e4b | #1 | 86.75 | 31.0 | 2644 | 3877 MB | 100% GPU | ✅ | - | 04.08.2026 | |
| qwen3-coder:30b | #1 | 48.32 | 120.5 | 2606 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 03.08.2026 | |
| gemma4:e4b | #1 | 83.16 | 73.3 | 2468 | 3877 MB | 100% GPU | ✅ | - | 03.08.2026 | |
| qwen3-coder:30b | #1 | 47.77 | 134.7 | 2411 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 02.08.2026 | |
| gemma4:e4b | #1 | 85.29 | 50.6 | 2633 | 3877 MB | 100% GPU | ✅ | - | 02.08.2026 | |
| qwen3-coder:30b | #1 | 44.23 | 102.1 | 2165 | 4752 MB | 19%/81% CPU/GPU | ✅ | - | 01.08.2026 | |
| gemma4:e4b | #1 | 85.93 | 50.7 | 2349 | 3845 MB | 100% GPU | ✅ | - | 01.08.2026 | |
| qwen3-coder:30b | #1 | 51.84 | 89.7 | 2609 | 4804 MB | 20%/80% CPU/GPU | ✅ | - | 31.07.2026 | |
| gemma4:e4b | #1 | 85.83 | 52.2 | 2116 | 3959 MB | 100% GPU | ✅ | - | 31.07.2026 | |
| qwen3-coder:30b | #1 | 47.35 | 145.9 | 2937 | 4804 MB | 20%/80% CPU/GPU | ✅ | - | 30.07.2026 | |
| gemma4:e4b | #1 | 85.04 | 55.6 | 2522 | 3959 MB | 100% GPU | ✅ | - | 30.07.2026 | |
| qwen3-coder:30b | #1 | 40.38 | 158.9 | 2786 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 29.07.2026 | |
| gemma4:e4b | #1 | 86.49 | 51.4 | 2204 | 3877 MB | 100% GPU | ✅ | - | 29.07.2026 | |
| qwen3-coder:30b | #1 | 46.99 | 58.5 | 2717 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 28.07.2026 | |
| gemma4:e4b | #1 | 85.49 | 31.6 | 2653 | 3877 MB | 100% GPU | ✅ | - | 28.07.2026 | |
| gemma4:e4b | #1 | 5.33 | 758.0 | 2534 | - | 100% CPU | ✅ | - | 27.07.2026 | |
| deepseek-coder-v2:16b | #1 | 13.10 | 89.1 | 1152 | - | 100% CPU | ✅ | - | 27.07.2026 | |
| gemma4:e4b | #1 | 8.53 | 337.5 | 2864 | - | 100% CPU | ✅ | - | 26.07.2026 | |
| deepseek-coder-v2:16b | #1 | 12.31 | 97.5 | 1187 | - | 100% CPU | ✅ | - | 26.07.2026 | |
| qwen3-coder:30b | #1 | 37.39 | 154.4 | 2739 | 4804 MB | 22%/78% CPU/GPU | ✅ | - | 25.07.2026 | |
| gemma4:e4b | #1 | 83.70 | 56.9 | 2522 | 3927 MB | 100% GPU | ✅ | - | 25.07.2026 | |
| qwen3-coder:30b | #1 | 40.68 | 58.5 | 2350 | 4804 MB | 22%/78% CPU/GPU | ✅ | - | 24.07.2026 | |
| gemma4:e4b | #1 | 84.08 | 29.2 | 2405 | 3927 MB | 100% GPU | ✅ | - | 24.07.2026 | |
| qwen3-coder:30b | #1 | 41.75 | 160.8 | 2788 | 4804 MB | 22%/78% CPU/GPU | ✅ | - | 23.07.2026 | |
| gemma4:e4b | #1 | 84.96 | 71.4 | 2531 | 3927 MB | 100% GPU | ✅ | - | 23.07.2026 | |
| qwen3-coder:30b | #1 | 49.03 | 57.8 | 2801 | 4804 MB | 22%/78% CPU/GPU | ✅ | - | 22.07.2026 | |
| gemma4:e4b | #1 | 83.54 | 33.6 | 2752 | 3927 MB | 100% GPU | ✅ | - | 22.07.2026 | |
| qwen3-coder:30b | #1 | 44.97 | 56.7 | 2518 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 20.07.2026 | |
| gemma4:e4b | #1 | 85.59 | 28.3 | 2370 | 3877 MB | 100% GPU | ✅ | - | 20.07.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.35 | 959.0 | 4096 | 4582 MB | 26%/74% CPU/GPU | ✅ | - | 19.07.2026 | — |
| qwen3-coder:30b | #1 | 40.78 | 69.8 | 2821 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 19.07.2026 | |
| gemma4:e4b | #1 | 86.16 | 31.6 | 2677 | 3877 MB | 100% GPU | ✅ | - | 19.07.2026 | |
| qwen3-coder:30b | #1 | 40.55 | 74.8 | 3007 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 18.07.2026 | |
| gemma4:e4b | #1 | 86.08 | 29.9 | 2523 | 3877 MB | 100% GPU | ✅ | - | 18.07.2026 | |
| qwen3-coder:30b | #1 | 43.34 | 134.8 | 2403 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 17.07.2026 | |
| gemma4:e4b | #1 | 84.01 | 53.5 | 2368 | 3877 MB | 100% GPU | ✅ | - | 17.07.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.54 | 914.1 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 14.07.2026 | |
| qwen3-coder:30b | #1 | 45.84 | 54.8 | 2478 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 14.07.2026 | |
| gemma4:e4b | #1 | 85.11 | 36.8 | 3082 | 3877 MB | 100% GPU | ✅ | - | 14.07.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.50 | 920.6 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 13.07.2026 | — |
| qwen3-coder:30b | #1 | 41.50 | 52.6 | 2154 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 13.07.2026 | |
| gemma4:e4b | #1 | 85.55 | 26.9 | 2254 | 3877 MB | 100% GPU | ✅ | - | 13.07.2026 | |
| qwen3:32b-q4_K_M | #1 | 3.82 | 1,081.1 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 12.07.2026 | — |
| qwen3-coder:30b | #1 | 48.14 | 59.5 | 2835 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 12.07.2026 | |
| gemma4:e4b | #1 | 85.73 | 30.6 | 2579 | 3877 MB | 100% GPU | ✅ | - | 12.07.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.44 | 923.7 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 11.07.2026 | — |
| qwen3-coder:30b | #1 | 42.25 | 60.4 | 2511 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 11.07.2026 | |
| gemma4:e4b | #1 | 85.77 | 28.0 | 2356 | 3877 MB | 100% GPU | ✅ | - | 11.07.2026 | |
| qwen3-coder:30b | #1 | 49.58 | 98.2 | 2404 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 10.07.2026 | |
| gemma4:e4b | #1 | 86.50 | 49.1 | 2323 | 3877 MB | 100% GPU | ✅ | - | 10.07.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.17 | 983.4 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 09.07.2026 | — |
| qwen3-coder:30b | #1 | 11.40 | 201.9 | 2287 | 3877 MB | 100% CPU | ✅ | - | 09.07.2026 | |
| gemma4:e4b | #1 | 8.91 | 270.5 | 2398 | 3877 MB | 100% CPU | ✅ | - | 09.07.2026 | |
| deepseek-coder-v2:16b | #1 | 17.84 | 72.2 | 1271 | 3877 MB | 100% CPU | ✅ | - | 09.07.2026 | |
| qwen3-coder:30b | #1 | 2.07 | 1,134.3 | 2329 | 4867 MB | - | ✅ | - | 05.07.2026 | |
| qwen3-coder:30b | #1 | 41.66 | 62.3 | 2564 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 02.07.2026 | |
| gemma4:e4b | #1 | 84.67 | 33.6 | 2799 | 3877 MB | 100% GPU | ✅ | - | 02.07.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.40 | 1,006.3 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 30.06.2026 | — |
| qwen3-coder:30b | #1 | 42.05 | 48.8 | 2023 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 30.06.2026 | |
| gemma4:e4b | #1 | 84.48 | 37.8 | 3146 | 3877 MB | 100% GPU | ✅ | - | 30.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.23 | 1,057.4 | 4096 | 5122 MB | - | ✅ | - | 29.06.2026 | — |
| qwen3-coder:30b | #1 | 41.22 | 67.6 | 2758 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 29.06.2026 | |
| gemma4:e4b | #1 | 84.89 | 30.6 | 2545 | 3877 MB | 100% GPU | ✅ | - | 29.06.2026 | |
| qwen3-coder:30b | #1 | 43.15 | 138.4 | 2647 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 28.06.2026 | |
| gemma4:e4b | #1 | 85.57 | 71.5 | 2534 | 3877 MB | 100% GPU | ✅ | - | 28.06.2026 | |
| qwen3-coder:30b | #1 | 41.01 | 138.4 | 2049 | 4867 MB | 19%/81% CPU/GPU | ✅ | - | 25.06.2026 | |
| gemma4:e4b | #1 | 83.06 | 72.5 | 2451 | 3877 MB | 100% GPU | ✅ | - | 25.06.2026 | |
| qwen3-coder:30b | #1 | 43.28 | 112.8 | 2571 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 24.06.2026 | |
| gemma4:e4b | #1 | 84.83 | 70.6 | 2440 | 3877 MB | 100% GPU | ✅ | - | 24.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.28 | 1,044.7 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 23.06.2026 | — |
| qwen3-coder:30b | #1 | 40.93 | 60.9 | 2465 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 23.06.2026 | |
| gemma4:e4b | #1 | 84.72 | 30.8 | 2563 | 3877 MB | 100% GPU | ✅ | - | 23.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.46 | 919.5 | 4096 | 4632 MB | - | ✅ | - | 21.06.2026 | — |
| qwen3-coder:30b | #1 | 41.84 | 75.8 | 3145 | 4804 MB | 20%/80% CPU/GPU | ✅ | - | 21.06.2026 | |
| gemma4:e4b | #1 | 85.27 | 36.3 | 3048 | 3927 MB | 100% GPU | ✅ | - | 21.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.47 | 1,067.5 | 4096 | 5174 MB | - | ✅ | - | 19.06.2026 | — |
| qwen3-coder:30b | #1 | 51.78 | 48.7 | 2485 | 4804 MB | 20%/80% CPU/GPU | ✅ | - | 19.06.2026 | |
| gemma4:e4b | #1 | 86.75 | 29.0 | 2471 | 3927 MB | 100% GPU | ✅ | - | 19.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.25 | 972.9 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 18.06.2026 | — |
| qwen3-coder:30b | #1 | 41.94 | 63.0 | 2617 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 18.06.2026 | |
| gemma4:e4b | #1 | 86.75 | 34.9 | 2978 | 3877 MB | 100% GPU | ✅ | - | 18.06.2026 | |
| qwen3-coder:30b | #1 | 40.16 | 139.7 | 2566 | 4850 MB | 20%/80% CPU/GPU | ✅ | - | 17.06.2026 | |
| gemma4:e4b | #1 | 86.57 | 69.2 | 2362 | 3877 MB | 100% GPU | ✅ | - | 17.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.24 | 1,094.0 | 4096 | 5122 MB | 25%/75% CPU/GPU | ✅ | - | 16.06.2026 | — |
| qwen3-coder:30b | #1 | 49.85 | 47.9 | 2354 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 16.06.2026 | |
| gemma4:e4b | #1 | 86.81 | 29.5 | 2514 | 3877 MB | 100% GPU | ✅ | - | 16.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.46 | 919.1 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 15.06.2026 | — |
| qwen3-coder:30b | #1 | 8.01 | 335.2 | 2673 | 3877 MB | 100% CPU | ✅ | - | 15.06.2026 | |
| gemma4:e4b | #1 | 8.80 | 291.0 | 2547 | 3877 MB | 100% CPU | ✅ | - | 15.06.2026 | |
| deepseek-coder-v2:16b | #1 | 16.17 | 70.3 | 1120 | 3877 MB | 100% CPU | ✅ | - | 15.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 3.87 | 1,060.2 | 4096 | 4665 MB | - | ✅ | - | 14.06.2026 | |
| qwen3-coder:30b | #1 | 41.31 | 139.4 | 2791 | 4782 MB | 19%/81% CPU/GPU | ✅ | - | 14.06.2026 | |
| gemma4:e4b | #1 | 8.33 | 319.6 | 2650 | 3877 MB | 100% CPU | ✅ | - | 14.06.2026 | |
| deepseek-coder-v2:16b | #1 | 15.90 | 68.9 | 1079 | 3877 MB | 100% CPU | ✅ | - | 14.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 3.94 | 1,152.1 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 13.06.2026 | — |
| qwen3-coder:30b | #1 | 48.29 | 60.0 | 2862 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 13.06.2026 | |
| gemma4:e4b | #1 | 84.67 | 29.4 | 2445 | 3877 MB | 100% GPU | ✅ | - | 13.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 3.60 | 1,151.3 | 4096 | 4582 MB | - | ✅ | - | 12.06.2026 | — |
| qwen3-coder:30b | #1 | 49.04 | 61.2 | 2965 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 12.06.2026 | |
| gemma4:e4b | #1 | 85.88 | 28.8 | 2426 | 3877 MB | 100% GPU | ✅ | - | 12.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 3.88 | 1,172.5 | 4096 | 4582 MB | 25%/75% CPU/GPU | ✅ | - | 11.06.2026 | — |
| qwen3-coder:30b | #1 | 49.66 | 53.3 | 2612 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 11.06.2026 | |
| gemma4:e4b | #1 | 85.65 | 39.1 | 3299 | 3877 MB | 100% GPU | ✅ | - | 11.06.2026 | |
| qwen3-coder:30b | #1 | 22.96 | 124.8 | 2837 | 4805 MB | 62%/38% CPU/GPU | ✅ | - | 09.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.30 | 1,199.4 | 4096 | 4582 MB | 26%/74% CPU/GPU | ✅ | - | 08.06.2026 | — |
| qwen3-coder:30b | #1 | 39.90 | 128.4 | 2699 | 4784 MB | 19%/81% CPU/GPU | ✅ | - | 08.06.2026 | |
| gemma4:e4b | #1 | 85.38 | 73.8 | 2727 | 3877 MB | 100% GPU | ✅ | - | 08.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.32 | 1,131.2 | 4096 | 5124 MB | - | ✅ | - | 07.06.2026 | — |
| qwen3-coder:30b | #1 | 47.50 | 51.3 | 2404 | 4850 MB | 20%/80% CPU/GPU | ✅ | - | 07.06.2026 | |
| gemma4:e4b | #1 | 86.54 | 29.8 | 2534 | 3877 MB | 100% GPU | ✅ | - | 07.06.2026 | |
| qwen3:32b-q4_K_M | #1 | 4.24 | 1,004.8 | 4096 | 5122 MB | 26%/74% CPU/GPU | ✅ | - | 06.06.2026 | — |
| qwen3-coder:30b | #1 | 43.02 | 58.1 | 2468 | 4850 MB | 20%/80% CPU/GPU | ✅ | - | 06.06.2026 | |
| gemma4:e4b | #1 | 87.25 | 26.2 | 2242 | 3877 MB | 100% GPU | ✅ | - | 06.06.2026 | |
| gemma4:12b-q4_K_M | #1 | 38.14 | 280.8 | 3208 | 8343 MB | 100% | ✅ | - | 04.06.2026 | |
| gemma4:e4b | #1 | 16.98 | 194.3 | 3253 | 15466 MB | - | ✅ | - | 01.06.2026 | |
| deepseek-coder-v2:16b | #1 | 16.98 | 79.0 | 1294 | 15296 MB | - | ✅ | - | 01.06.2026 | |
| qwen3-coder:30b | #1 | 18.12 | 136.6 | 2439 | 15279 MB | - | ✅ | - | 31.05.2026 | |
| gemma4:e4b | #1 | 32.80 | 76.1 | 2423 | 12253 MB | - | ✅ | - | 31.05.2026 | |
| deepseek-coder-v2:16b | #1 | 51.67 | 23.4 | 1128 | 15319 MB | - | ✅ | - | 31.05.2026 | |
| qwen3-coder:30b | #1 | 17.30 | 154.1 | 2630 | 15205 MB | - | ✅ | - | 30.05.2026 | |
| gemma4:e4b | #1 | 31.46 | 86.1 | 2633 | 12185 MB | - | ✅ | - | 30.05.2026 | |
| deepseek-coder-v2:16b | #1 | 53.43 | 27.3 | 1363 | 15245 MB | - | ✅ | - | 30.05.2026 | |
| gemma4:e4b | #1 | 32.65 | 76.8 | 2435 | 13010 MB | - | ✅ | - | 28.05.2026 | |
| deepseek-coder-v2:16b | #1 | 42.32 | 32.0 | 1275 | 15201 MB | - | ✅ | - | 28.05.2026 | |
| qwen3-coder:30b | #1 | 16.04 | 489.9 | 2672 | 15402 MB | - | ✅ | - | 27.05.2026 | |
| gemma4:e4b | #1 | 28.88 | 207.4 | 3030 | 12593 MB | - | ✅ | - | 27.05.2026 | |
| deepseek-coder-v2:16b | #1 | 44.46 | 58.7 | 1208 | 15258 MB | - | ✅ | - | 27.05.2026 | |
| qwen3-coder:30b | #1 | 7.31 | 367.8 | 2660 | - | - | ✅ | - | 25.05.2026 | |
| gemma4:e4b | #1 | 7.28 | 339.7 | 2428 | - | - | ✅ | - | 25.05.2026 | |
| deepseek-coder-v2:16b | #1 | 12.97 | 91.7 | 1133 | - | - | ✅ | - | 25.05.2026 | |
| qwen3-coder:30b | #1 | 6.61 | 421.2 | 2752 | - | - | ✅ | - | 24.05.2026 | |
| gemma4:e4b | #1 | 3.30 | 825.3 | 2700 | - | - | ✅ | - | 24.05.2026 | |
| deepseek-coder-v2:16b | #1 | 10.78 | 121.3 | 1262 | - | - | ✅ | - | 24.05.2026 | |
| qwen3-coder:30b | #1 | 6.71 | 436.2 | 2899 | - | - | ✅ | - | 23.05.2026 | |
| gemma4:e4b | #1 | 7.17 | 343.8 | 2378 | - | - | ✅ | - | 23.05.2026 | |
| deepseek-coder-v2:16b | #1 | 12.71 | 111.4 | 1353 | - | - | ✅ | - | 23.05.2026 | |
| qwen3-coder:30b | #1 | 9.07 | 575.9 | 2432 | 15394 MB | - | ✅ | - | 21.05.2026 | |
| gemma4:e4b | #1 | 17.88 | 283.5 | 2521 | 14859 MB | - | ✅ | - | 21.05.2026 | |
| deepseek-coder-v2:16b | #1 | 15.84 | 149.4 | 1220 | 15153 MB | - | ✅ | - | 21.05.2026 | |
| deepseek-coder-v2:16b | #1 | 14.76 | 116.5 | 1217 | 15478 MB | - | ✅ | - | 19.05.2026 | |
| deepseek-coder-v2:16b | #1 | 16.66 | 73.9 | 1187 | 15476 MB | - | ✅ | - | 19.05.2026 | |
| qwen3-coder:30b | #1 | 9.17 | 318.3 | 2578 | 15456 MB | - | ✅ | - | 19.05.2026 | |
| gemma4:e4b | #1 | 16.99 | 174.3 | 2918 | 14292 MB | - | ✅ | - | 19.05.2026 | |
| deepseek-coder-v2:16b | #1 | 17.42 | 81.0 | 1363 | 15536 MB | - | ✅ | - | 19.05.2026 | |
| qwen3-coder:30b | #1 | 8.84 | 393.8 | 2308 | 15461 MB | - | ✅ | - | 18.05.2026 | |
| deepseek-coder-v2:16b | #1 | 17.25 | 103.5 | 1273 | 15541 MB | - | ✅ | - | 18.05.2026 | |
| gemma4:e4b | #1 | 17.82 | 156.4 | 2744 | 14310 MB | - | ✅ | - | 18.05.2026 |
Vygenerované výstupy
qwen3-coder:30b
# Interactive Galaxy Particle Animation
I'll create an impressive 3D particle animation that simulates a galaxy with 5000 colorful particles, responsive to mouse movement, and includes a starfield background.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Galaxy Particle Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
margin: 8px 0;
font-size: 1rem;
line-height: 1.4;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
font-family: monospace;
font-size: 1.2rem;
}
#instructions {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 12px 25px;
border-radius: 30px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
text-align: center;
font-size: 1rem;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Galaxy Particle Animation</h1>
<p>• 5000 colorful particles rotating in a spiral galaxy</p>
<p>• Mouse movement tilts the galaxy</p>
<p>• Starfield background for depth</p>
<p>• Real-time FPS counter</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy • Click and drag to rotate</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 100;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add orbit controls for mouse interaction
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy particles in spiral pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral galaxy formation
const radius = Math.sqrt(Math.random()) * 100;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (Math.random() * 0.5 + 0.5); // Blue to purple range
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.3 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random particle sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create particle material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Mouse movement handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 2;
mouseY = (event.clientY - windowHalfY) / 2;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate particles
if (particles) {
particles.rotation.y += 0.001;
// Mouse interaction
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update FPS counter
stats.fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${stats.fps}`;
renderer.render(scene, camera);
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this Galaxy Animation:
1. **5000 Colorful Particles**: Created in a spiral galaxy pattern with vibrant colors
2. **Interactive Controls**:
- Mouse movement tilts the galaxy
- Click and drag to rotate the view
3. **Sta
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy animation with 5000 particles that respond to mouse movement and include a starfield background with FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
cursor: move;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.8);
font-size: 24px;
font-weight: bold;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
}
#fps {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
</style>
</head>
<body>
<div id="container">
<div id="title">Interactive 3D Galaxy Simulation</div>
<div id="info">5,000 Particles | Mouse Tilt | Galaxy Spiral</div>
<div id="fps">FPS: 0</div>
<div id="instructions">Move mouse to tilt the galaxy | Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let stats, clock;
let particleCount = 5000;
let galaxyRadius = 300;
let galaxyRotationSpeed = 0.001;
let starField;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 500, 1500);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarField();
// Add lighting
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1, 1000);
pointLight.position.set(0, 0, 0);
scene.add(pointLight);
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Initialize clock for FPS
clock = new THREE.Clock();
// Start animation loop
animate();
}
// Create the galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create particles in a spiral galaxy pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral pattern with some randomness
const radius = Math.random() * galaxyRadius;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
// Spiral arms
const spiralAngle = angle + Math.sin(angle * 0.3) * 0.5;
const spiralRadius = radius * (1 + Math.sin(spiralAngle * 2) * 0.3);
positions[i3] = Math.cos(spiralAngle) * spiralRadius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(spiralAngle) * spiralRadius;
// Color variations - blue to yellow to white
const color = new THREE.Color();
const hue = (Math.sin(i * 0.01) * 0.5 + 0.5) * 0.3; // Blue to yellow range
color.setHSL(hue, 1, 0.5);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 3 + 1;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarField() {
const starGeometry = new THREE.BufferGeometry();
const starPositions = [];
const starColors = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starPositions.push(x, y, z);
// Star colors (mostly white with some blue/amber)
const color = new THREE.Color();
const hue = Math.random() > 0.7 ? 0.1 : Math.random() > 0.5 ? 0.2 : 0.0;
color.setHSL(hue, 0.3, Math.random() * 0.5 + 0.5);
starColors.push(color.r, color.g, color.b);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
starGeometry.setAttribute('color', new THREE.Float32BufferAttribute(starColors, 3));
const starMaterial = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.8
});
starField = new THREE.Points(starGeometry, starMaterial);
scene.add(starField);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update FPS counter
const delta = clock.getDelta();
const fps = Math.round(1 / delta);
document.getElementById('fps').textContent = `FPS: ${fps}`;
// Rotate galaxy
if (particleSystem) {
particleSystem.rotation.y += galaxyRotationSpeed;
}
// Mouse tilt effect
if (controls) {
controls.autoRotate = false;
camera.position.x += (mouseX * 10 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 10 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
//
gemma4:e4b
This is a complete, single-file implementation that uses Three.js to create the required particle animation.
To ensure the best performance and visual quality, we will use `BufferGeometry` for the particles and implement a basic FPS counter using time measurement within the render loop.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Spiral Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#info-overlay {
position: absolute;
top: 15px;
left: 15px;
padding: 10px;
background: rgba(0, 0, 0, 0.6);
color: #ffffff;
font-family: 'Arial', sans-serif;
border-radius: 8px;
z-index: 10; /* Ensure it sits above the canvas */
}
</style>
</head>
<body>
<div id="info-overlay">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdn.jsdelivr.net/npm/three@r/build/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
const particleCount = 5000;
let mouseX = 0;
let mouseY = 0;
// FPS Counter variables
let frameCount = 0;
let lastTime = performance.now();
const overlay = document.getElementById('info-overlay');
/**
* Initializes the Three.js environment: scene, camera, renderer.
*/
function init() {
// 1. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 2. Scene Setup
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000); // Deep space black
// 3. Camera Setup (Perspective camera works well for depth)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 50;
// --- Create Particles ---
createGalaxySpiral();
createStarField();
// --- Event Listeners ---
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
// Start the animation loop
animate();
}
/**
* Generates the spiraling galaxy structure using BufferGeometry for efficiency.
*/
function createGalaxySpiral() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const radiusScale = 10; // Controls how far out the spiral goes
const numParticles = particleCount;
for (let i = 0; i < numParticles; i++) {
// Calculate position based on index for a continuous spiral effect
const t = i / numParticles * Math.PI * 5; // Angle increases over time
const r = radiusScale * (1 + (i % 10) / 20); // Modulate radial distance slightly
// Spiral Formula: x = r*cos(t), y = r*sin(t)*y_mod, z = r*sin(t)*z_mod
const x = r * Math.cos(t);
const y = r * Math.sin(t) * (0.5 + 0.5 * Math.cos(t / 2)); // Adds vertical curvature
const z = r * Math.sin(t) * (0.5 + 0.5 * Math.sin(t / 2));
positions.push(x, y, z);
// Generate random colors for a colorful effect
const color = new THREE.Color();
color.setHSL(i / numParticles, 1.0, 0.6); // Hue based on index
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors attribute stored in the geometry
transparent: true,
opacity: 0.9
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a dense background starfield using simple random points.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const vertices = [];
// Generate stars in a large cube volume (-100, 100)
for (let i = 0; i < particleCount * 2; i++) { // More particles for starfield
vertices.push(
(Math.random() - 0.5) * 300, // x: -150 to 150
(Math.random() - 0.5) * 300, // y: -150 to 150
(Math.random() - 0.5) * 300 // z: -150 to 150
);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
const material = new THREE.PointsMaterial({
size: 0.1,
color: 0xffffff,
transparent: true,
opacity: 0.8
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
/**
* Handles window resizing to keep the canvas fullscreen.
*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates mouse tracking variables based on cursor movement.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX / window.innerWidth) * 2 - 1; // Normalized to -1 to 1
mouseY = -(event.clientY / window.innerHeight) * 2 - 1;
}
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now();
const delta = (time - lastTime) / 1000; // Time elapsed since last frame in seconds
// --- Animation Logic ---
// 1. Galaxy Rotation (Self-rotation and overall sweep)
galaxyParticles.rotation.y += 0.0005;
galaxyParticles.rotation.x += 0.0002;
// Make the particles appear to orbit slightly over time by adjusting their position based on time
const positions = galaxyParticles.geometry.attributes.position.array;
for (let i = 0; i < particleCount; i++) {
// Simple sinusoidal movement along the Z axis for a pulsing effect
positions[i * 3 + 2] += Math.sin(time * 0.001 + i * 0.05) * 0.001;
}
galaxyParticles.geometry.attributes.position.needsUpdate = true;
// 2. Starfield Movement (Simulates gentle parallax/movement)
starFieldParticles.rotation.y += 0.00005;
// 3. Interaction Response (Mouse Tilt)
// Use the mouse variables to rotate the camera or scene slightly, simulating looking around
camera.position.x = Math.sin(mouseX * 0.5) * 2;
camera.position.y = Math.cos(mouseY * 0.5) * 2;
camera.lookAt(scene.position); // Keep the camera focused on the center
// --- Rendering and FPS Update ---
renderer.render(scene, camera);
updateFPS(delta);
lastTime = time;
}
/**
* Simple function to calculate and display the current Frame Rate (FPS).
*/
function updateFPS(deltaTime) {
frameCount++;
const elapsed = performance.now() - lastTime; // We use a separate timer here for smoother FPS calculation
// Calculate FPS every half second
if (elapsed >= 500) {
const fps = Math.round((frameCount * 1000) / elapsed);
overlay.innerHTML = `FPS: ${fps}`;
// Reset counters for the next interval
frameCount = 0;
lastTime = performance.now(); // Reset last time to current time
} else {
// Optional: Update continuously if needed, but sampling every half second is usually enough.
}
}
// Initialize everything when the script loads
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive Galaxy Particle Animation
I'll create an interactive 3D particle animation with a galaxy-like spiral, responsive to mouse movement, with a starfield background and FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
cursor: move;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.9);
font-size: 24px;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.8);
letter-spacing: 2px;
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
</style>
</head>
<body>
<div id="container">
<div id="title">INTERACTIVE GALAXY PARTICLE ANIMATION</div>
<div id="info">Drag to rotate | Scroll to zoom</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move mouse to tilt galaxy | Click and drag to rotate</div>
</div>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats = { fps: 0, lastTime: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
// Create galaxy particles in spiral pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.random() * 300;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 100;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy colors (blues, purples, yellows)
const color = new THREE.Color();
const hue = Math.random() * 0.4 + 0.5; // Blue to purple range
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.3 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update FPS counter
const delta = clock.getDelta();
stats.fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${stats.fps}`;
// Rotate particles
if (particles) {
particles.rotation.x += 0.0002;
particles.rotation.y += 0.0005;
// Mouse tilt effect
camera.position.x += (mouseX * 5 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 5 - camera.position.y) * 0.05;
}
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
}
// Initialize the application
init();
</script>
</body>
</html>
```
## Features of this Interactive Galaxy Animation:
1. **Galaxy Particle System**: 5000 colorful particles arranged in a spiral galaxy pattern with vibrant blues, purples, and yellows
2. **Mouse Interaction**:
- Drag to rotate the galaxy view
- Mouse movement tilts the galaxy
- Scroll to zoom in/out
3. **Starfield Background**: 10,000 stars scattered throughout space for a cosmic feel
4. **FPS Counter**: Displays real-time frames per second in the bottom-right corner
5. **Responsive Design**: Adapts to any screen size
6. **Smooth Animations**:
- Continuous rotation of particles
- Smooth camera controls with damping
- Mouse tilt effect for interactive experience
7. **Visual Effects**:
- Particle transparency and size attenuation
- Colorful particle distribution
- Glowing title and UI elements
The animation creates a mesmerizing galaxy effect with smooth, continuous motion that responds to user interaction. The starfield background adds depth and context to the particle system, while the FPS
gemma4:e4b
This is a complex animation that requires careful setup of Three.js geometry and advanced JavaScript logic for interaction and performance monitoring.
Here is the complete, single HTML file containing all the required functionality.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 10px;
left: 10px;
background-color: rgba(0, 0, 0, 0.5);
color: #ffffff;
padding: 8px 15px;
border-radius: 5px;
font-family: 'Arial', sans-serif;
font-size: 16px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<!-- Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
let mouseX = 0, mouseY = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
// Performance tracking variables
let frameCount = 0;
let lastTime = performance.now();
const fpsDiv = document.getElementById('fpsCounter');
// --- Initialization Function ---
function init() {
// Scene setup
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000011, 0.0005); // Deep space fog
// Camera setup (Perspective for depth)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// Renderer setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// --- Create Components ---
createGalaxyParticles();
createStarfield();
// --- Event Listeners ---
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Start the animation loop
animate();
}
/**
* Generates particles in a spiral galaxy configuration.
*/
function createGalaxyParticles() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Parameters for spiral shape (Archimedean/logarithmic curve approximation)
const maxAngle = Math.PI * 6; // Full 3 rotations
const maxRadius = 100;
const depthVariation = 50;
for (let i = 0; i < particleCount; i++) {
// Distribute particles evenly over the angle
const theta = (i / particleCount) * maxAngle;
// Calculate radius: r increases with angle for a spiral effect
// Using Math.pow(theta, 0.5) makes it look more like a disk initially and then widens out.
let r = maxRadius * Math.sqrt(Math.sin(theta));
// Position coordinates
const x = r * Math.cos(theta);
const y = r * Math.sin(theta) * 0.5; // Squish the Y axis slightly for disk look
// Z position (depth variation - makes it look like a plane)
const z = depthVariation * Math.sin(theta / 2);
positions.push(x, y, z);
// Assign random vibrant colors
color.setHSL(0.6 + i / particleCount * 0.4, 1.0, 0.5); // HSL cycle for color variation
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup for the galaxy (requires vertex colors)
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true,
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a sparse, fixed starfield background.
*/
function createStarfield() {
const particleCount = 15000;
const geometry = new THREE.BufferGeometry();
const positions = [];
// Stars are spread randomly in a large cube volume
for (let i = 0; i < particleCount; i++) {
// Random coordinates within a large cube centered at the origin
const x = THREE.MathUtils.randFloatSpread(500);
const y = THREE.MathUtils.randFloatSpread(200);
const z = THREE.MathUtils.randFloatSpread(500);
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material setup for stars (simple white points)
const material = new THREE.PointsMaterial({
size: 0.1,
color: 0xaaaaee,
transparent: true,
blending: THREE.AdditiveBlending // Makes them glow nicely
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
// --- Event Handlers ---
function onWindowResize() {
camera.viewport = new THREE.Vector2(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
// Normalize mouse coordinates (-1 to +1)
mouseX = (event.clientX - windowHalfX) / window.innerWidth;
mouseY = (event.clientY - windowHalfY) / window.innerHeight;
}
// --- Animation Loop and Logic ---
function animate(time) {
requestAnimationFrame(animate);
const delta = time - lastTime;
lastTime = time;
// 1. Update Galaxy Rotation (Continuous Spin)
galaxyParticles.rotation.y += 0.0002;
galaxyParticles.rotation.x += 0.0001;
// 2. Mouse Interaction (Tilt/LookAt)
// Smoothly move the camera target based on mouse position
const targetX = Math.sin(mouseX * Math.PI * 2) * 5; // Scale down the effect
const targetY = Math.cos(mouseY * Math.PI * 2) * 5;
camera.lookAt(targetX, targetY, -10);
// 3. Starfield Rotation (Subtle movement)
starfieldParticles.rotation.y += 0.00005;
starfieldParticles.rotation.x = Math.sin(time * 0.00005) * 0.1;
// 4. Render the scene
renderer.render(scene, camera);
// 5. Update FPS Counter
frameCount++;
const elapsedSeconds = (performance.now() - lastTime) / 1000;
if (elapsedSeconds >= 0.5) { // Update counter every half second for stability
const fps = Math.round(frameCount / elapsedSeconds);
fpsDiv.textContent = `FPS: ${fps}`;
frameCount = 0;
}
}
// Start everything!
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an interactive 3D particle animation with 5000 colorful particles rotating in a galaxy-like spiral, responding to mouse movement and featuring a starfield background.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
max-width: 300px;
}
#info h1 {
font-size: 24px;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 163, 0.3);
}
#info p {
font-size: 14px;
line-height: 1.5;
margin-bottom: 10px;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
font-family: monospace;
font-size: 16px;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
text-align: center;
backdrop-filter: blur(5px);
font-size: 14px;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive Galaxy Simulation</h1>
<p>This 3D particle animation features:</p>
<p>• <span class="highlight">5000</span> colorful particles in a galaxy spiral</p>
<p>• <span class="highlight">Mouse interaction</span> - tilt to rotate the galaxy</p>
<p>• <span class="highlight">Starfield background</span> with twinkling stars</p>
<p>• <span class="highlight">Real-time FPS counter</span></p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 4;
const height = (Math.random() - 0.5) * 40;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color based on position and time
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) % 1;
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 3 + 1;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
// Create particle system
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Create starfield background
function createStarfield() {
const starCount = 10000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(starCount * 3);
const colors = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
// Position stars in a sphere around the galaxy
const radius = 500 + Math.random() * 1000;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positions[i3 + 2] = radius * Math.cos(phi);
// Star colors (white to blue)
const color = new THREE.Color();
color.setHSL(0.65 + Math.random() * 0.1, 0.5, 0.7 + Math.random() * 0.3);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.8
});
const stars = new THREE.Points(geometry, material);
scene.add(stars);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.01;
mouseY = (event.clientY - windowHalfY) * 0.01;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate galaxy based on mouse position
if (particles) {
particles.rotation.y += 0.001;
particles.rotation.x = mou
gemma4:e4b
This is a comprehensive implementation that utilizes Three.js for performance, advanced geometry manipulation for the spiral effect, and event listeners for interactivity, all contained within a single HTML file.
Due to the complexity and size, ensure you are running this code in a modern browser environment.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.8);
font-family: monospace;
font-size: 16px;
padding: 10px;
background: rgba(0, 0, 0, 0.5);
border-radius: 5px;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 60</div>
<!-- Load Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let particleSystem;
const NUM_PARTICLES = 5000;
const galaxyGroup = new THREE.Object3D(); // Group to hold particles for rotation/tilt
// Mouse tracking variables for interactivity
const mouse = { x: 0.0, y: 0.0 };
let previousMouseX = 0;
let previousMouseY = 0;
// FPS tracking
let frameCount = 0;
let lastTime = performance.now();
const fpsElement = document.getElementById('fpsCounter');
/**
* Initializes the scene, camera, and renderer.
*/
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
// Add a subtle ambient light (though point particles are emissive)
const ambientLight = new THREE.AmbientLight(0x444466, 1);
scene.add(ambientLight);
// 2. Camera Setup
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 3. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. Create Particle System (Galaxy Spiral)
createParticles();
// 5. Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove);
// Start the animation loop
animate();
}
/**
* Generates the particles in a spiral formation using parametric equations.
*/
function createParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const sizes = [];
// --- Spiral Generation Logic ---
for (let i = 0; i < NUM_PARTICLES; i++) {
// Normalized index for spiral calculation
const t = i / NUM_PARTICLES * Math.PI * 6; // Controls the number of turns (e.g., 6 full turns)
// Calculate radius (r) and angle (theta) for a logarithmic spiral: r = a * e^(b*t)
const r = Math.pow(i / NUM_PARTICLES, 0.5) * 4 + Math.random() * 3; // Scales the spread
const theta = t - (Math.sin(i/10) * 2); // Adds wobble
// Cartesian coordinates: x = r * cos(theta), z = r * sin(theta)
// Y is used for depth variation in a galaxy plane, making it slightly curved.
const x = Math.cos(theta) * r * (1 + Math.sin(t / 2)); // X component
const y = Math.random() * 2 - 1; // Small vertical random offset
const z = Math.sin(theta) * r * (1 + Math.cos(t / 2)); // Z component
positions.push(x, y, z);
// Random colorful glow for the particles
const color = new THREE.Color();
color.setHSL(i / NUM_PARTICLES, 0.8, 0.5 + Math.random() * 0.3);
colors.push(color.r, color.g, color.b);
// Size variation
sizes.push(Math.random() * 2 + 1);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.Float32BufferAttribute(sizes, 1));
// --- Material Setup ---
const material = new THREE.PointsMaterial({
size: 1.5, // Base size
vertexColors: true, // Use the color attribute for vertex coloring
blending: THREE.AdditiveBlending, // Creates a glowing effect
transparent: true,
opacity: 0.8
});
particleSystem = new THREE.Points(geometry, material);
galaxyGroup.add(particleSystem);
scene.add(galaxyGroup);
}
/**
* Handles window resizing to keep the aspect ratio correct.
* @param {Event} event - The resize event.
*/
function onWindowResize() {
camera.viewport = { x: 0, y: 0, width: 1, height: 1 };
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Tracks mouse movement for interactive camera tilt effect.
* @param {MouseEvent} event - The mouse move event.
*/
function onMouseMove(event) {
const deltaX = event.clientX - previousMouseX;
const deltaY = event.clientY - previousMouseY;
// Smooth movement mapping (scaling the input difference)
mouse.x = deltaX * 0.001;
mouse.y = deltaY * 0.001;
previousMouseX = event.clientX;
previousMouseY = event.clientY;
}
/**
* The main animation loop (render cycle).
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() / 1000;
// --- Animation Logic ---
// 1. Rotation (Galaxy Spin)
galaxyGroup.rotation.y += 0.0005; // Slow, constant rotation around Y-axis
galaxyGroup.rotation.x = Math.sin(time * 0.2) * 0.1; // Gentle wobble on X
// 2. Mouse Interaction (Tilt/Camera LookAt Simulation)
// Smoothly apply the mouse offset to the camera and group rotation
camera.rotation.y += mouse.x * 0.5;
camera.rotation.x += mouse.y * 0.1;
// 3. Update FPS Counter
frameCount++;
const currentTime = performance.now();
if (currentTime - lastTime >= 1000) {
const fps = Math.round(frameCount / ((currentTime - lastTime) / 1000));
fpsElement.textContent = `FPS: ${fps}`;
lastTime = currentTime;
frameCount = 0;
}
// Render the scene
renderer.render(scene, camera);
}
// --- Initialization Call ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy simulation with 5000 particles that respond to mouse movement, a starfield background, and an FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
z-index: 10;
max-width: 300px;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff758c);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 126, 179, 0.3);
}
#info p {
font-size: 1rem;
margin-bottom: 15px;
line-height: 1.5;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
font-family: monospace;
z-index: 10;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 30px;
backdrop-filter: blur(5px);
text-align: center;
font-size: 0.9rem;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive Galaxy Simulation</h1>
<p>This 3D particle animation features:</p>
<ul>
<li>5000 colorful particles in a spiral galaxy pattern</li>
<li>Real-time mouse interaction (tilt effect)</li>
<li>Starfield background with depth</li>
<li>FPS counter for performance monitoring</li>
<li>Smooth animations and visual effects</li>
</ul>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Scroll to zoom in/out</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 50, 150);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 100;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add lighting
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1, 1000);
pointLight.position.set(50, 50, 50);
scene.add(pointLight);
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.addEventListener('wheel', onMouseWheel);
// Start animation loop
animate();
}
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(i) * 0.5;
const angle = i * 0.02 + Math.sin(i * 0.001) * 0.5;
const height = (Math.sin(i * 0.001) * 0.5) * 20;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (i / particleCount) * 0.5 + 0.5; // Blue to purple
const saturation = 0.8 + Math.sin(i * 0.01) * 0.2;
const lightness = 0.3 + Math.cos(i * 0.01) * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create particle material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
function createStarfield() {
const starCount = 10000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(starCount * 3);
const colors = new Float32Array(starCount * 3);
const sizes = new Float32Array(starCount);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
// Position stars in a spherical distribution
const radius = 500 + Math.random() * 1000;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positions[i3 + 2] = radius * Math.cos(phi);
// Star colors (mostly white with some blue/yellow)
const color = new THREE.Color();
if (Math.random() > 0.7) {
color.setHSL(0.1, 0.5, 0.8); // Blue stars
} else if (Math.random() > 0.5) {
color.setHSL(0.15, 0.3, 0.9); // Yellow stars
} else {
color.setRGB(1, 1, 1); // White stars
}
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 1.5 + 0.2;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 1,
vertexColors: true,
transparent: true,
opacity: 0.8
});
const starfield = new THREE.Points(geometry, material);
scene.add(starfield);
}
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.01;
mouseY = (event.clientY - windowHalfY) * 0.01
gemma4:e4b
This is a complex, highly visual request that requires integrating physics/math simulations (the spiral generation), graphics rendering (Three.js), and performance monitoring (FPS counter) into one file.
The solution below uses modern JavaScript practices within a single HTML file structure.
### Interactive 3D Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Spiral Particles</title>
<style>
/* Basic reset and full screen setup */
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
/* Style the FPS counter overlay */
#fps-counter {
position: fixed;
top: 10px;
right: 10px;
background-color: rgba(0, 0, 0, 0.6);
color: #FFFFFF;
padding: 5px 10px;
border-radius: 8px;
font-family: monospace;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 60</div>
<!-- Three.js CDN Link -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- GLOBAL SETUP VARIABLES ---
let scene, camera, renderer;
let galaxyParticles, starField;
let clock = new THREE.Clock();
let mouseX = 0;
let mouseY = 0;
// --- FPS MONITORING ---
let frameCount = 0;
let lastTime = performance.now();
const fpsCounterElement = document.getElementById('fps-counter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000); // Black background
// 2. Camera Setup (Perspective view)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 50);
// 3. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// --- CREATE ELEMENTS ---
createGalaxyParticles();
createStarField();
// 4. Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onMouseMove, false);
}
/**
* Generates the spiral galaxy particle system.
*/
function createGalaxyParticles() {
const numParticles = 5000;
const positions = [];
const colors = [];
const colorMesh = new THREE.Color();
// Create a gradient of colors for visual appeal
for (let i = 0; i < numParticles; i++) {
// Calculate position based on spiral formula (r = theta * n)
// Theta determines the angle, and 'i' determines how far along the spiral we are.
const theta = Math.random() * Math.PI * 2; // Random base angle
const r = Math.sqrt(Math.random()) * 40; // Radius (spread)
// Spiral effect: makes particles further out have a higher 'i' correlation
const z_spiral = (r / 15) + Math.sin(theta * 2) * 10;
// Convert polar to cartesian coordinates for the spiral structure
const x = r * Math.cos(theta);
const y = r * Math.sin(theta) * 0.8; // Slightly flattening along Y
const z = z_spiral;
positions.push(x, y, z);
// Assign random colors and cycle them for a colorful effect
colorMesh.setHSL(i / numParticles, 1.0, 0.5 + Math.random() * 0.3);
colors.push(colorMesh.r, colorMesh.g, colorMesh.b);
}
// Geometry and Material setup
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Important: uses the colors attribute
transparent: true,
opacity: 0.9
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Generates a dense starfield background (static points).
*/
function createStarField() {
const starsGeometry = new THREE.BufferGeometry();
const positions = [];
const numStars = 15000;
for (let i = 0; i < numStars; i++) {
// Scatter stars randomly within a large cube
const x = (Math.random() - 0.5) * 200;
const y = (Math.random() - 0.5) * 200;
const z = (Math.random() - 0.5) * 200;
positions.push(x, y, z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
size: 1.5,
color: 0xaaaaaa,
transparent: true
});
starField = new THREE.Points(starsGeometry, material);
scene.add(starField);
}
// --- INTERACTION HANDLERS ---
/**
* Updates camera position/rotation based on mouse movement (tilt effect).
* @param {MouseEvent} event
*/
function onMouseMove(event) {
mouseX = (event.clientX - window.innerWidth / 2) * 0.1;
mouseY = (event.clientY - window.innerHeight / 2) * 0.1;
}
/**
* Handles window resizing to keep the scene scaled correctly.
*/
function onWindowResize() {
camera.viewport.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// --- ANIMATION LOOP AND LOGIC ---
/**
* Updates the particle positions for movement and rotation.
* @param {number} delta Time elapsed since last frame (seconds).
*/
function updateParticles(delta) {
const time = clock.getElapsedTime();
// 1. Galaxy Rotation: Spin around Y axis smoothly
galaxyParticles.rotation.y += 0.05 * delta;
// 2. Spiral effect: Make the particles gently pulse and drift
const positions = galaxyParticles.geometry.attributes.position.array;
for (let i = 0; i < 5000; i++) {
// Scale factor based on time to create a pulsing, breathing effect
const scalePulse = Math.sin(time * 0.8 + i * 0.01) * 0.5 + 1.0;
// Apply pulse and slow horizontal drift (cos/sin of time)
positions[i * 3] *= scalePulse; // X
positions[i * 3 + 1] *= scalePulse; // Y
positions[i * 3 + 2] = Math.cos(time * 0.5 + i * 0.005) * 5; // Z drift
}
galaxyParticles.geometry.attributes.position.needsUpdate = true;
// 3. Starfield Movement (Subtle parallax/drift)
starField.rotation.y += delta * 0.001; // Slow rotation
}
/**
* Main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// --- Update Logic ---
updateParticles(delta);
// --- Camera & Rendering (Tilt response) ---
// Smoothly interpolate the camera target based on mouse movement
camera.position.x += (mouseX * 0.1 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 0.1 - camera.position.y) * 0.05;
// Tilt the entire view slightly based on mouse input
camera.rotation.z = mouseY * 0.02;
camera.rotation.x = mouseX * 0.02;
renderer.render(scene, camera);
// --- FPS Counter Update ---
frameCount++;
const time = performance.now();
if (time - lastTime >= 1000) { // Check every second
const fps = Math.round(frameCount / ((time - lastTime) / 1000));
fpsCounterElement.textContent = `FPS: ${fps}`;
lastTime = time;
frameCount = 0;
}
}
// --- START THE APPLICATION ---
init();
animate();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy simulation with 5000 colorful particles that respond to mouse movement and include a starfield background with FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
font-family: 'Arial', sans-serif;
}
canvas {
display: block;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-size: 14px;
z-index: 100;
background-color: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: white;
font-size: 24px;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.7);
z-index: 100;
letter-spacing: 2px;
}
#instructions {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
}
</style>
</head>
<body>
<div id="title">INTERACTIVE GALAXY SIMULATION</div>
<div id="info">FPS: <span id="fps-counter">0</span></div>
<div id="instructions">Move your mouse to tilt the galaxy | Click and drag to rotate</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
2000
);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
document.addEventListener('mousedown', onMouseDown);
document.addEventListener('mouseup', onMouseUp);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleGeometry = new THREE.BufferGeometry();
const particleMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
// Create galaxy with spiral arms
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral arm parameters
const radius = Math.random() * 200;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 40;
// Position particles in spiral pattern
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) * 0.5 + 0.5; // Blue to red transition
const saturation = 0.7 + Math.random() * 0.3;
const lightness = 0.4 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
}
// Mouse movement handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Mouse down handler for rotation
let isDragging = false;
let previousMousePosition = { x: 0, y: 0 };
function onMouseDown(event) {
isDragging = true;
previousMousePosition = {
x: event.clientX,
y: event.clientY
};
}
function onMouseUp() {
isDragging = false;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Rotate particles
if (particles) {
particles.rotation.x = elapsedTime * 0.05;
particles.rotation.y = elapsedTime * 0.1;
// Apply mouse tilt effect
if (!isDragging) {
camera.position.x += (mouseX * 50 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 50 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
}
// Handle dragging rotation
if (isDragging) {
const deltaX = event.clientX - previousMousePosition.x;
const deltaY = event.clientY - previousMousePosition.y;
particles.rotation.y += deltaX * 0.01;
particles.rotation.x += deltaY * 0.01;
previousMousePosition = {
x: event.clientX,
y: event.clientY
};
}
// Update FPS counter
const fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = fps;
// Render the scene
renderer.render(scene, camera);
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this Interactive Galaxy Animation:
1. **5000 Colorful Particles**: Created in a galaxy-like spiral pattern with vibrant colors
2. **Mouse Interaction**:
- Move mouse to tilt the galaxy
- Click and drag to rotate the entire galaxy
3. **Starfield Background**: 10,000 stars creating a deep space environment
4. **FPS Counter**: Real-time performance indicator in the top-left corner
5. **Smooth Animations**:
- Continuous rotation of particles
- Smooth camera movements
- Responsive to user interaction
6. **Responsive Design**: Adapts to any screen size
7. **Visual Appeal**:
- Dark space background with glowing particles
- Colorful spiral arms with gradient hues
- Subtle transparency effects
The animation uses Three.js for 3D rendering and includes performance optimization techniques like buffer geometries and efficient animation loops. The galaxy rotates smoothly while responding to mouse movements for an immersive experie
gemma4:e4b
This is a complex setup requiring efficient geometry handling and continuous updates in JavaScript. Since we are using Three.js, performance is critical, so we will use `BufferGeometry` for the particles.
Here is the complete single HTML file solution:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particle Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: 'Courier New', monospace';
padding: 5px 10px;
background: rgba(0, 0, 0, 0.6);
border-radius: 5px;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<!-- Load Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starfield;
const NUM_GALACTIC_PARTICLES = 5000;
const NUM_STARFIELD_PARTICLES = 10000;
// Mouse tracking for interactivity (tilt effect)
let mouseX = 0, mouseY = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
// FPS Counter Variables
let frameCount = 0;
let lastTime = performance.now();
const fpsElement = document.getElementById('fpsCounter');
/**
* Initialization function: Sets up the scene, camera, and renders initial objects.
*/
function init() {
// Scene setup
scene = new THREE.Scene();
// Camera setup (Perspective is best for depth)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.set(0, 0, 50); // Start slightly back
// Renderer setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Create the visual components
createStarfield();
createGalaxyParticles();
// Start the animation loop
animate();
}
/**
* 1. Creates a dense, slow-moving background starfield.
*/
function createStarfield() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
for (let i = 0; i < NUM_STARFIELD_PARTICLES; i++) {
// Random position far away
positions.push((Math.random() - 0.5) * 4000); // x
positions.push((Math.random() - 0.5) * 4000); // y
positions.push(Math.random() * 1000 + 500); // z (keep them far enough back)
// Random color for star twinkle effect
const color = new THREE.Color();
color.setHSL(Math.random(), 0.7, Math.random());
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1.5, // Star size
vertexColors: true, // Use the colors defined in the geometry
transparent: true,
opacity: 0.8
});
starfield = new THREE.Points(geometry, material);
scene.add(starfield);
}
/**
* 2. Creates the main galaxy structure using a spiral equation.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
for (let i = 0; i < NUM_GALACTIC_PARTICLES; i++) {
// --- Spiral Math Implementation ---
// Radius increases linearly with angle/index
const r = (i / NUM_GALACTIC_PARTICLES) * 150 + 10;
// Angle determines position around the spiral center
const theta = (i / NUM_GALACTIC_PARTICLES) * Math.PI * 4; // Multiplied by 4 for tighter spirals
// Z depth determines how far back it is (creates depth effect)
const z = r * 0.5 + Math.random() * 10;
// Calculate coordinates using polar to Cartesian conversion: x=r*cos(theta), y=r*sin(theta)
const x = Math.cos(theta) * r;
const y = Math.sin(theta) * r * 0.5 + (Math.random() - 0.5) * 20; // Slightly flatten the vertical profile
positions.push(x);
positions.push(y);
positions.push(z);
// Color assignment: Gradient colors based on position or index for effect
const color = new THREE.Color();
color.setHSL(i / NUM_GALACTIC_PARTICLES, 0.8, Math.random() * 0.5 + 0.3); // Hue shift across the galaxy
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1.5, // Particle size
vertexColors: true, // Crucial for coloring individual particles
transparent: true,
opacity: 0.9,
blending: THREE.AdditiveBlending // Makes colors glow together
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
// --- Event Handlers ---
/**
* Handles mouse movement for camera tilt effect.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.8; // Scale down movement sensitivity
mouseY = (event.clientY - windowHalfY) * 0.8;
}
/**
* Handles window resizing to keep the animation full screen.
*/
function onWindowResize() {
camera.viewport.set(0, 0, 1, 1);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// --- Animation Loop and Logic ---
/**
* Main animation loop called by requestAnimationFrame.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() / 1000; // Time in seconds
// 1. Particle Movement (Rotation & Depth)
galaxyParticles.rotation.y += 0.001;
galaxyParticles.rotation.x = Math.sin(time * 0.2) * 0.05;
// Make the particles pulse/shift slightly over time
const positions = galaxyParticles.geometry.attributes.position.array;
for (let i = 0; i < NUM_GALACTIC_PARTICLES; i++) {
// Subtle depth movement based on time
positions[i * 3 + 2] += Math.sin(time * 0.5 + i) * 0.01;
}
galaxyParticles.geometry.attributes.position.needsUpdate = true;
// 2. Starfield Movement (Simulating camera drift through space)
starfield.rotation.y += 0.0005;
starfield.translateY(-time * 5); // Slow vertical scroll
// 3. Camera Interaction (Tilt based on mouse position)
// Smoothly interpolate the camera rotation towards the desired tilt offset
camera.rotation.x += (mouseY * 0.0001 - camera.rotation.x) * 0.1;
camera.rotation.y += (mouseX * 0.0001 - camera.rotation.y) * 0.1;
// 4. Render Scene
renderer.render(scene, camera);
// 5. FPS Calculation
frameCount++;
const elapsed = performance.now() - lastTime;
if (elapsed >= 1000) {
const fps = Math.round(frameCount * 1000 / elapsed);
fpsElement.textContent = `FPS: ${fps}`;
// Reset for next measurement interval
frameCount = 0;
lastTime = performance.now();
}
}
// --- Execution Start ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an interactive 3D particle animation with a galaxy-like spiral, mouse tilt response, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
max-width: 300px;
z-index: 10;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff758c);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 117, 140, 0.5);
}
#info p {
margin-bottom: 15px;
font-size: 1rem;
line-height: 1.5;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
backdrop-filter: blur(5px);
z-index: 10;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
text-align: center;
backdrop-filter: blur(5px);
font-size: 0.9rem;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>This visualization features:</p>
<p>• <span class="highlight">5000 colorful particles</span> in a galaxy spiral</p>
<p>• <span class="highlight">Mouse tilt interaction</span> for dynamic viewing</p>
<p>• <span class="highlight">Starfield background</span> with twinkling stars</p>
<p>• <span class="highlight">Real-time FPS counter</span></p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy • Scroll to zoom in/out</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats;
let starField;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 15, 30);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 25;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create starfield background
createStarField();
// Create galaxy particles
createGalaxy();
// Add lighting
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(5, 5, 5);
scene.add(pointLight);
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarField() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.1,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 5000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
starField = new THREE.Points(starGeometry, starMaterial);
scene.add(starField);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const galaxyRadius = 15;
const armCount = 4;
const armWidth = 0.8;
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy particles
for (let i = 0; i < particleCount; i++) {
const radius = Math.random() * galaxyRadius;
const angle = Math.random() * Math.PI * 2;
// Spiral arms
const armAngle = angle + (Math.sin(radius * 0.5) * 0.5);
const spiralRadius = radius * (1 + Math.sin(armAngle * armCount) * armWidth);
const x = Math.cos(armAngle) * spiralRadius;
const y = Math.sin(armAngle) * spiralRadius;
const z = (Math.random() - 0.5) * 3;
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
// Color based on position
const color = new THREE.Color();
const hue = (radius / galaxyRadius) * 0.5 + 0.5; // From blue to red
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
// Size variation
sizes[i] = Math.random() * 0.5 + 0.2;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 0.1,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Mouse movement handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.01;
mouseY = (event.clientY - windowHalfY) * 0.01;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Update controls
controls.update();
// Rotate galaxy based on mouse position
if (particleSystem) {
particleSystem.rotation.y += 0.001 + mouseX * 0.002;
particleSystem.rotation.x = mouseY * 0.1;
}
// Rotate starfield slowly
if (starField) {
starField.rotation.x
gemma4:e4b
This is a complex, high-performance visualization that requires careful handling of WebGL resources. The solution uses Three.js to create a large particle system simulating a spiral galaxy, links camera movement to mouse input for interactivity, and includes an FPS counter for real-time feedback.
**Note:** Since this is a single file, the JavaScript code will be substantial. Run it in a modern browser environment (like Chrome or Firefox) to see the full effect.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: rgba(255, 255, 255, 0.7);
font-family: monospace;
padding: 5px;
background-color: rgba(0, 0, 0, 0.4);
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: --</div>
<!-- Include Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
const particleCount = 5000;
const totalParticles = particleCount + 1000; // Galaxy + Starfield
let mouseX = 0.0;
let mouseY = 0.0;
// --- FPS Counter Variables ---
let lastTime = performance.now();
let frameCount = 0;
const fpsDisplay = document.getElementById('fps-counter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// Scene Setup
scene = new THREE.Scene();
// Camera Setup (Perspective for depth)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.set(0, 0, 50); // Start slightly back to see the galaxy
// Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove);
// Create the particle systems
createGalaxyParticles();
createStarField();
// Start the animation loop
animate();
}
/**
* Generates 5000 particles in a spiral/galaxy pattern.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Spiral Galaxy Logic: r = constant * angle, z = sin(angle), x = cos(angle)
for (let i = 0; i < particleCount; i++) {
// Calculate position based on spiral function and random offset
const angle = (i / particleCount) * Math.PI * 6 + Math.random() * 2 * Math.PI; // Spiral rotation base
const distanceFactor = Math.pow(Math.random(), 1.5); // Keeps density higher near the center
// Spiral coordinates: X = R*cos(theta), Y = sin(theta)*scale, Z = cos(theta)*scale
let x = Math.sin(angle) * (distanceFactor * 20 + 10);
let y = Math.random() * 5 - 2.5; // Vertical spread
let z = Math.cos(angle) * (distanceFactor * 20 + 10);
positions.push(x, y, z);
// Assign random colors for visual impact
const color = new THREE.Color();
color.setHSL(Math.random(), 0.8, Math.random() * 0.6 + 0.4); // Hue-based coloring
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use per-particle colors
transparent: true,
opacity: 0.8,
blending: THREE.AdditiveBlending // Makes them glow when overlapping
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a simple, distant starfield background (1000 particles).
*/
function createStarField() {
const geometry = new THREE.SphereGeometry(500, 64, 64);
// We only need the vertices for positions
geometry.setAttribute('position', 'position');
// Use a neutral material since stars are tiny and distant
const material = new THREE.PointsMaterial({
size: 1.5,
color: 0xAAAAFF,
transparent: true,
opacity: 0.6
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
/**
* Handles window resizing to maintain aspect ratio.
*/
function onWindowResize() {
camera.viewport.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates mouse coordinates used for camera tilt effects.
*/
function onMouseMove(event) {
// Normalize mouse coordinates to the range of [-1, 1]
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* The main animation loop. Updates particle positions and renders the scene.
* @param {number} time - Current timestamp from requestAnimationFrame.
*/
function animate(time) {
requestAnimationFrame(animate);
// --- Interactivity (Tilt Effect) ---
// Smoothly interpolate camera rotation based on mouse movement
const targetRotationX = mouseY * 0.1; // Tilt up/down
const targetRotationY = mouseX * 0.1; // Pan left/right
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.05;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.05;
// --- Galaxy Rotation and Movement ---
const timeFactor = time * 0.0001;
// Rotate the galaxy around its central vertical axis
galaxyParticles.rotation.z += 0.002;
galaxyParticles.rotation.y += 0.005;
// Apply a slight pulsation/breathing effect to the particles' scale
const pulse = Math.sin(timeFactor * 1.5) * 0.01 + 1.0;
galaxyParticles.scale.setScalar(pulse);
// --- Starfield Movement (Subtle rotation for depth illusion) ---
starFieldParticles.rotation.y += 0.0005;
// Render the scene
renderer.render(scene, camera);
// Update FPS counter
updateFPS(time);
}
/**
* Calculates and displays the current Frames Per Second (FPS).
* @param {number} currentTime - Current timestamp.
*/
function updateFPS(currentTime) {
const delta = currentTime - lastTime; // Time elapsed since last frame in ms
frameCount++;
// Update FPS every half second for stability
if (delta >= 500) {
let fps = Math.round(1000 / (delta / frameCount));
fpsDisplay.textContent = `FPS: ${fps}`;
// Reset counters
frameCount = 0;
lastTime = currentTime;
}
}
// --- Execution Start ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive 3D particle galaxy animation with mouse interaction and starfield background using Three.js. Here's the complete solution:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
cursor: none;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.9);
font-size: 28px;
font-weight: 300;
letter-spacing: 2px;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 8px 12px;
border-radius: 8px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
z-index: 100;
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="title">3D GALAXY PARTICLE ANIMATION</div>
<div id="info">Interactive Galaxy Simulation | 5000 Particles | Mouse Tilt Control</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Scroll to zoom</div>
</div>
<!-- Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
document.addEventListener('wheel', onMouseWheel);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
// Create spiral galaxy pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) * 0.5 + 0.5;
const saturation = 0.7 + Math.random() * 0.3;
const lightness = 0.4 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.0005;
mouseY = (event.clientY - windowHalfY) * 0.0005;
}
// Mouse wheel handler for zoom
function onMouseWheel(event) {
camera.position.z += event.deltaY * 0.01;
camera.position.z = Math.min(Math.max(camera.position.z, 200), 1000);
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate particles slowly
if (particles) {
particles.rotation.x = elapsed * 0.05;
particles.rotation.y = elapsed * 0.03;
}
// Mouse tilt effect
camera.position.x += (mouseX * 100 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 100 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
// Update FPS counter
const fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${fps}`;
}
// Initialize the application
init();
</script>
</body>
</html>
```
## Features of this 3D Galaxy Animation:
1. **Galaxy Visualization**:
- 5000 colorful particles arranged in a spiral galaxy pattern
- Particles have varying colors and sizes for a realistic look
- Smooth rotation animation
2. **Interactive Elements**:
- Mouse movement tilts the galaxy (x and y axes)
- Scroll to zoom in/out of the galaxy
- OrbitControls for additional navigation
3. **Visual Enhancements**:
- Starfield background with 10,000 stars
- Smooth animations and transitions
- Responsive design that works on all screen sizes
- FPS counter in the corner showing performance
gemma4:e4b
This solution provides a complete, single-file HTML implementation that uses Three.js for the 3D rendering, CSS for styling, and JavaScript for all animation logic, including particle generation, galaxy movement, mouse tracking, and FPS counting.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #00001a; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-family: 'Arial', sans-serif;
padding: 10px;
background: rgba(0, 0, 0, 0.4);
border-radius: 5px;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<!-- Include Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
let mouseX = 0, mouseY = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
// --- FPS Counter Variables ---
let frameCount = 0;
let lastTime = performance.now();
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// Scene setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Initial camera position
camera.position.z = 50;
// --- Create Particle Systems ---
createGalaxyParticles(5000);
createStarfieldBackground(10000);
// Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
animate();
}
/**
* Generates the main galaxy particle system in a spiral pattern.
* @param {number} count The number of particles to generate.
*/
function createGalaxyParticles(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Simulate a spiral distribution using polar coordinates and variation
for (let i = 0; i < count; i++) {
// Angle increases linearly to form the spiral structure
const theta = (i / count) * Math.PI * 4; // Multiplier controls tightness of spiral
// Radius varies based on angle and index, simulating arms
let r = 10 + Math.sin(theta * 2) * 5 + Math.random() * 3;
// Depth (Z position) gives the sense of volume/depth
const z = Math.cos(i / count * Math.PI); // Particles distributed along a Z axis curve
// X and Y positions using polar to cartesian conversion
positions.push(r * Math.sin(theta), r * Math.cos(theta) * 0.5, z);
// Color generation (randomized for color depth effect)
const color = new THREE.Color();
color.setHSL(i / count % 1.0, 1.0, 0.7); // Hue changes gradually
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.15,
vertexColors: true, // Use the colors stored in the geometry
transparent: true,
opacity: 0.9
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a distant starfield background for depth perception.
* @param {number} count The number of stars to generate.
*/
function createStarfieldBackground(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < count; i++) {
// Place stars far away in a large cube volume
const x = (Math.random() - 0.5) * 4000;
const y = (Math.random() - 0.5) * 4000;
const z = (Math.random() - 0.5) * 4000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Stars use a softer material and are larger to fill space
const material = new THREE.PointsMaterial({
size: 1.5,
color: '#ffffff',
transparent: true,
opacity: 0.8
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
/**
* Handles screen resizing to keep the canvas correct.
*/
function onWindowResize() {
camera.viewport = new THREE.Vector2(0, 0);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates mouse coordinates for camera tilt effect.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.5; // Scale down the movement sensitivity
mouseY = (event.clientY - windowHalfY) * 0.5;
}
/**
* The main animation loop.
* @param {number} time Current timestamp for smooth rotation.
*/
function animate(time) {
requestAnimationFrame(() => animate(time));
const delta = (time - lastTime) / 1000; // Time elapsed since last frame in seconds
lastTime = time;
frameCount++;
// --- Camera Tilt Response (Mouse Look) ---
// Smoothly interpolates the camera rotation based on mouse input
camera.rotation.x += (mouseY * 0.001 - camera.rotation.x) * 0.05;
camera.rotation.y += (mouseX * 0.001 - camera.rotation.y) * 0.05;
// --- Galaxy Rotation and Movement ---
const timeFactor = time * 0.0001;
// 1. Slow rotation around the Y-axis
galaxyParticles.rotation.y += 0.0005;
starfieldParticles.rotation.y += 0.0002;
// 2. Subtle pulsation/movement effect for the galaxy (scaling)
galaxyParticles.scale.set(1 + Math.sin(timeFactor * 0.5) * 0.01, 1 + Math.cos(timeFactor * 0.3) * 0.01, 1);
// --- Render and Update FPS ---
renderer.render(scene, camera);
updateFPS(frameCount, time);
}
/**
* Updates the displayed Frame Rate counter.
*/
function updateFPS(count, currentTime) {
const elapsedSeconds = (currentTime - lastTime) / 1000; // This is a rough measure since we only update on frame end
// A more accurate FPS calculation requires tracking time over multiple frames
if (!updateFPS.lastTotalTime) {
updateFPS.lastTotalTime = currentTime;
}
const totalElapsedTime = (currentTime - updateFPS.lastTotalTime);
let fps = Math.round(frameCount / (totalElapsedTime / 1000));
// Simple smoothing for visual stability
if (!window.fps) window.fps = [];
window.fps.push(fps);
if (window.fps.length > 10) window.fps.shift();
const averageFPS = Math.round(window.fps.reduce((a, b) => a + b) / window.fps.length);
document.getElementById('fpsCounter').innerText = `FPS: ${averageFPS}`;
}
// Start the animation when everything is ready
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive 3D galaxy animation with 5000 particles that respond to mouse movement, a starfield background, and an FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
font-family: 'Arial', sans-serif;
}
canvas {
display: block;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-size: 14px;
background-color: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
pointer-events: none;
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: white;
font-size: 24px;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.7);
pointer-events: none;
opacity: 0.8;
}
#instructions {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
pointer-events: none;
}
</style>
</head>
<body>
<div id="title">Interactive 3D Galaxy</div>
<div id="info"></div>
<div id="instructions">Move your mouse to tilt the galaxy | Click and drag to rotate</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let stats, clock;
let galaxyCenter = new THREE.Vector3(0, 0, 0);
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add lighting
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1, 1000);
pointLight.position.set(100, 100, 100);
scene.add(pointLight);
// Initialize clock for FPS
clock = new THREE.Clock();
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create the galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create particles in a spiral galaxy pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral galaxy formation
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color variations for a galaxy effect
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) + (Math.random() * 0.2 - 0.1);
const saturation = 0.7 + Math.random() * 0.3;
const lightness = 0.5 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Window resize handler
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update controls
controls.update();
// Rotate particles
if (particleSystem) {
particleSystem.rotation.y += 0.001;
particleSystem.rotation.x = mouseY * 0.2;
particleSystem.rotation.z = mouseX * 0.05;
}
// Update FPS counter
updateFPS();
// Render the scene
renderer.render(scene, camera);
}
// Update FPS display
function updateFPS() {
const delta = clock.getDelta();
const fps = Math.round(1 / delta);
const info = document.getElementById('info');
if (info) {
info.textContent = `FPS: ${fps}`;
}
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this 3D Galaxy Animation:
1. **5000 Colorful Particles**: Created in a realistic spiral galaxy pattern with varying colors and sizes
2. **Interactive Controls**:
- Mouse movement tilts the galaxy
- Click and drag to rotate the entire scene
3. **Starfield Background**: Thousands of stars create a cosmic backdrop
4. **Real-time FPS Counter**: Displays current frames per second in the top-left corner
5. **Smooth Animations**: Optimized with Three.js for fluid performance
6. **Responsive Design**: Adapts to any screen size
7. **Visual Effects**:
- Particle colors vary for a galaxy-like appearance
- Depth-based particle sizing
- Smooth rotation and movement
The animation creates an immersive experience with a beautiful spiral galaxy effect that responds naturally to user interaction. The FPS counter helps monitor performance, and the starfield background adds depth to the scene.
Simply open this HTML file in any modern browser to enjoy the interactive 3D galaxy!
gemma4:e4b
This is a complex animation that requires careful handling of Three.js concepts (geometry, materials, rendering loops, event listeners). The following code provides a complete, standalone implementation using modern JavaScript practices for high performance.
### Interactive Galactic Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particles</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-family: 'Arial', sans-serif;
font-size: 18px;
padding: 10px;
background: rgba(0, 0, 0, 0.4);
border-radius: 5px;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
const NUM_GALACTIC = 5000;
const NUM_STARS = 15000;
// Mouse tracking for interaction
let mouseX = 0;
let mouseY = 0;
// FPS Tracking variables
let frameCount = 0;
let lastTime = performance.now();
let fpsElement = document.getElementById('fps-counter');
/**
* Initializes the Three.js environment (Scene, Camera, Renderer).
*/
function init() {
// Scene setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set camera position (looking into the center of the galaxy)
camera.position.set(0, 0, 50);
camera.lookAt(0, 0, 0);
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove);
// Create particle systems
createGalaxyParticles();
createStarField();
// Start the animation loop
animate();
}
/**
* Generates particles arranged in a spiral/galaxy pattern.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// The spiral logic: r = A * theta, z = B * theta (approximating a flat spiral)
for (let i = 0; i < NUM_GALACTIC; i++) {
const t = i / (NUM_GALACTIC / Math.PI); // Parameter from 0 to PI*N/NUM_GALACTIC
// Spiral radius and Z position
const r = (i / NUM_GALACTIC) * 80; // Radius increases with index
const theta = t * 1.5; // Angle changes faster for spiral effect
// Calculate Cartesian coordinates based on the spiral formula
const x = Math.cos(theta) * r;
const y = (Math.random() - 0.5) * 2; // Slight vertical jitter
const z = Math.sin(theta) * r * 0.8;
positions.push(x, y, z);
// Assign random bright colors for variety
color.setHSL(i / NUM_GALACTIC + 0.5, 1, 0.6);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup (Using PointsMaterial for simplicity and performance)
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors defined in the geometry
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Generates a random starfield background using many small points.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < NUM_STARS; i++) {
// Distribute stars widely in a large sphere
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a simple material for the stars
const material = new THREE.PointsMaterial({
size: 1,
color: 0xaaaaee, // Faint blue/white color
transparent: true,
opacity: 0.7
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
/**
* Handles window resizing to keep the renderer responsive.
*/
function onWindowResize() {
camera.viewport = { x: 0, y: 0, width: 1, height: 1 };
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Captures mouse movement and stores offsets for camera tilt effect.
*/
function onMouseMove(event) {
// Normalize coordinates (-1 to +1 range)
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() * 0.001; // Time in seconds
// --- Particle Logic (Galaxy Rotation) ---
galaxyParticles.rotation.y += 0.0005;
galaxyParticles.rotation.x = Math.sin(time * 0.2) * 0.05; // Slow oscillation rotation
// --- Interaction/Camera Tilt ---
// Use mouse coordinates to subtly adjust the camera's rotation and position
const targetRotationX = mouseY * 0.1;
const targetRotationY = mouseX * 0.1;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.05;
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.05;
// --- Starfield Logic (Subtle movement/parallax effect) ---
starFieldParticles.rotation.y += 0.0001; // Very slow rotation for depth illusion
// Render the scene and update FPS counter
renderer.render(scene, camera);
updateFPS();
}
/**
* Calculates and displays the Frames Per Second (FPS).
*/
function updateFPS() {
const now = performance.now();
const elapsed = now - lastTime;
// Calculate FPS: 1000ms / time_elapsed
const fps = Math.round(1000 / elapsed);
fpsElement.textContent = `FPS: ${fps}`;
lastTime = now;
}
// Start the entire application
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an interactive 3D particle animation that simulates a galaxy with 5000 colorful particles, responsive to mouse movement, and includes a starfield background.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
max-width: 300px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
font-size: 1rem;
line-height: 1.5;
margin-bottom: 15px;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 30px;
text-align: center;
font-size: 0.9rem;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive Galaxy Simulation</h1>
<p>This 3D particle animation features:</p>
<ul>
<li>5,000 colorful particles in a galaxy spiral</li>
<li>Real-time mouse interaction (tilt effect)</li>
<li>Starfield background</li>
<li>FPS performance counter</li>
<li>Smooth animations</li>
</ul>
<p>Move your mouse to tilt the galaxy and explore the cosmic depths!</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move mouse to interact | <span class="highlight">Click and drag</span> to rotate view</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create the galaxy particle system
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 40;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color variations for galaxy effect
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) + Math.random() * 0.2;
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes for particles
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starCount = 2000;
const starGeometry = new THREE.BufferGeometry();
const starPositions = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
// Random positions in a sphere
const radius = 1000 + Math.random() * 5000;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
starPositions[i3] = radius * Math.sin(phi) * Math.cos(theta);
starPositions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
starPositions[i3 + 2] = radius * Math.cos(phi);
}
starGeometry.setAttribute('position', new THREE.BufferAttribute(starPositions, 3));
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starField = new THREE.Points(starGeometry, starMaterial);
scene.add(starField);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate galaxy based on mouse position
if (particleSystem) {
particleSystem.rotation.y += 0.001 + mouseX * 0.002;
particleSystem.rotation.x += mouseY * 0.001;
gemma4:e4b
This is a complete, self-contained HTML file that uses Three.js to create the interactive particle animation as requested.
Due to the complexity and performance requirements (5000 particles + advanced interactivity), I have included robust optimization techniques like using `BufferGeometry` for efficient rendering and implementing a dedicated FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: 'Arial', sans-serif;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 60</div>
<!-- Load Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Initialization ---
let scene, camera, renderer;
let particlesMesh;
const particleCount = 5000;
let mouseX = 0;
let mouseY = 0;
// FPS Tracking variables
let frameCount = 0;
let lastTime = performance.now();
const fpsElement = document.getElementById('fps-counter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// Renderer setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Scene setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 0;
// Event Listeners for resizing and mouse tracking
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove);
createParticles();
}
/**
* Creates the particle system with a spiral galaxy structure.
*/
function createParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Generate particles in a spiral pattern (simulated)
for (let i = 0; i < particleCount; i++) {
// Calculate position based on index 'i' to create a gradient/spiral effect
const angle = (i / particleCount) * Math.PI * 4 + (Math.random() - 0.5); // Spiral rotation factor
const radius = Math.pow(i / particleCount, 1.5) * 200; // Radius increases with index
// Z-coordinate depth component for the spiral structure
const zOffset = (Math.sin(angle * 3 + i * 0.01) * radius * 0.5);
// X and Y coordinates define the main plane spiral
positions.push(Math.cos(angle) * radius, Math.sin(angle) * radius, zOffset);
// Assign random colorful attributes
color.setHSL(i / particleCount, 1.0, 0.5 + Math.random() * 0.3);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup (PointsMaterial is best for particles)
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true, // Use the colors assigned in the geometry
transparent: true,
opacity: 0.8
});
particlesMesh = new THREE.Points(geometry, material);
scene.add(particlesMesh);
}
/**
* Handles window resizing to keep the aspect ratio correct.
*/
function onWindowResize() {
camera.viewport = { x: 0, y: 0, width: 1, height: 1 };
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates mouse coordinates globally and applies camera tilt.
*/
function onDocumentMouseMove(event) {
// Normalize mouse coordinates (-1 to +1)
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* The main animation loop function.
*/
function animate(time) {
requestAnimationFrame(animate);
const delta = (time - lastTime) / 1000;
lastTime = time;
// --- 1. Galaxy Rotation and Movement ---
const rotationSpeed = 0.002 * delta * 60; // Smooth rotational speed
// Rotate the entire particle system around the Y-axis (main spiral effect)
particlesMesh.rotation.y += rotationSpeed;
// Subtle automatic breathing/pulsing motion
particlesMesh.scale.x = 1 + Math.sin(time * 0.0005) * 0.02;
particlesMesh.scale.y = 1 + Math.cos(time * 0.0004) * 0.02;
// --- 2. Mouse Interaction (Tilt) ---
// Apply camera rotation based on mouse position for tilt effect
camera.rotation.x += mouseY * 0.0001;
camera.rotation.y += mouseX * 0.0001;
// Render the scene
renderer.render(scene, camera);
// --- 3. FPS Counter Update ---
frameCount++;
}
/**
* Calculates and displays the current Frames Per Second (FPS).
*/
function updateFPS() {
const now = performance.now();
const elapsedSeconds = (now - lastTime) / 1000; // Use actual time difference for accurate FPS calculation
// Calculate average FPS over a short interval
let fps = Math.round(frameCount / elapsedSeconds);
fpsElement.textContent = `FPS: ${Math.max(10, fps)}`; // Ensure minimum display value
}
// --- Execution Flow ---
init();
animate(performance.now());
// Set up a timed interval for FPS updates (runs every 500ms)
setInterval(() => {
updateFPS();
frameCount = 0; // Reset count for the next measurement period
lastTime = performance.now(); // Reset timer base
}, 500);
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D particle galaxy animation using Three.js with mouse tilt responsiveness and a starfield background.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
max-width: 300px;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 163, 0.3);
}
#info p {
font-size: 1rem;
line-height: 1.5;
margin-bottom: 15px;
}
#controls {
display: flex;
gap: 10px;
margin-top: 10px;
}
#controls button {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.3);
color: white;
padding: 8px 15px;
border-radius: 20px;
cursor: pointer;
transition: all 0.3s ease;
}
#controls button:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateY(-2px);
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
backdrop-filter: blur(5px);
}
#loading {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: #000;
z-index: 200;
transition: opacity 1s ease;
}
.spinner {
width: 50px;
height: 50px;
border: 5px solid rgba(255, 255, 255, 0.1);
border-top: 5px solid #ff7eb3;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
#loading-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 1.2rem;
text-align: center;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>This simulation features <span class="highlight">5000 colorful particles</span> forming a galaxy-like spiral.</p>
<p>Move your mouse to tilt the galaxy and explore the cosmos!</p>
<div id="controls">
<button id="resetBtn">Reset View</button>
<button id="speedUpBtn">Speed Up</button>
<button id="slowDownBtn">Slow Down</button>
</div>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="loading">
<div class="spinner"></div>
<div id="loading-text">Initializing Galaxy...</div>
</div>
</div>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats = { fps: 0, rotationSpeed: 0.002 };
let animationId;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.getElementById('resetBtn').addEventListener('click', resetView);
document.getElementById('speedUpBtn').addEventListener('click', () => stats.rotationSpeed += 0.001);
document.getElementById('slowDownBtn').addEventListener('click', () => stats.rotationSpeed = Math.max(0.0005, stats.rotationSpeed - 0.001));
// Hide loading screen
setTimeout(() => {
document.getElementById('loading').style.opacity = '0';
setTimeout(() => {
document.getElementById('loading').style.display = 'none';
}, 1000);
}, 1500);
// Start animation
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleGeometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy particles with spiral pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral pattern
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 40;
const x = Math.cos(angle) * radius;
const y = Math.sin(angle) * radius;
const z = height;
positions[i3] = x;
positions[i3 + 1] = y;
positions[i3 + 2] = z;
// Color variation
const color = new THREE.Color();
const hue = (Math.random() * 0.5 + 0.5) % 1; // Blue to purple
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.3 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Size variation
sizes[i] = Math.random() * 2 + 0.5;
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particleGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const particleMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
}
// Mouse move
gemma4:e4b
This is a comprehensive and visually demanding task that utilizes several advanced features of Three.js, including geometric calculation, event handling, and performance monitoring.
Here is the complete single-file solution.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000; }
canvas { display: block; }
/* Style for the FPS Counter */
#fpsCounter {
position: absolute;
top: 10px;
right: 20px;
color: rgba(255, 255, 255, 0.6);
font-family: monospace;
font-size: 14px;
pointer-events: none; /* Ensures it doesn't block mouse events on the canvas */
user-select: none;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Setup Variables ---
let scene, camera, renderer;
let particlesGalaxy, particleGeometry, particleMaterial;
let starfieldParticles = [];
const PARTICLE_COUNT = 5000;
let mouseX = 0;
let mouseY = 0;
// Performance tracking variables
let lastTime = performance.now();
let fpsCounterElement = document.getElementById('fpsCounter');
/**
* 1. INITIALIZATION FUNCTION
*/
function init() {
// --- Scene Setup ---
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set camera position and initial look
camera.position.z = 50;
// --- Event Listeners ---
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove, false);
// --- Create Elements ---
createGalaxyParticles();
createStarfieldBackground(10000); // 10,000 stars for depth
// Start the animation loop
animate();
}
/**
* 2. GALACTIC PARTICLE GENERATION (The Spiral)
*/
function createGalaxyParticles() {
particleGeometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// We will generate particles along a spiral path and add some randomness
for (let i = 0; i < PARTICLE_COUNT; i++) {
// Normalized index (0 to 1)
const t = i / (PARTICLE_COUNT - 1);
// Spiral parameters: r = a * theta, z = b * theta
// The 't' value controls the progress along the spiral.
const radius = Math.pow(Math.sin(t * Math.PI * 2), 0.5) * 40; // Radial spread
const angle = t * Math.PI * 3; // Angular rotation (3 full rotations)
// Position coordinates (X, Y, Z)
const x = Math.cos(angle) * radius + (Math.random() - 0.5) * 10;
const y = Math.sin(angle) * radius + (Math.random() - 0.5) * 10;
// Z controls the depth/spiral effect, making it look like a plane rotating around an axis
const z = t * 80 - 40 + (Math.random() - 0.5) * 5;
positions.push(x, y, z);
// Generate random colors for visual appeal
const color = new THREE.Color();
color.setHSL(t / PARTICLE_COUNT, 1.0, Math.random()); // Hue changes over the spiral
colors.push(color.r, color.g, color.b);
}
// Set attributes
particleGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup (Using Vertex Colors for individual particle colors)
particleMaterial = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Important: tells the material to use the vertex color attribute
transparent: true,
opacity: 0.8
});
particlesGalaxy = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particlesGalaxy);
}
/**
* 3. STARFIELD BACKGROUND GENERATION
*/
function createStarfieldBackground(count) {
const starpositions = [];
const positions = [];
for (let i = 0; i < count; i++) {
// Random positions far away from the origin, simulating deep space
const x = (Math.random() - 0.5) * 4000;
const y = (Math.random() - 0.5) * 4000;
// Z is large to ensure depth and a starfield look
const z = Math.random() * 2000 - 1000;
starpositions.push(x, y, z);
}
const starGeometry = new THREE.BufferGeometry();
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starpositions, 3));
// Use a single point material for all stars (white/blue)
const starMaterial = new THREE.PointsMaterial({
size: 1.5,
color: 0xaaaaee,
transparent: true,
opacity: 0.7
});
starfieldParticles = new THREE.Points(starGeometry, starMaterial);
scene.add(starfieldParticles);
}
/**
* 4. INTERACTION HANDLERS
*/
function onWindowResize() {
camera.viewport.setSize(window.innerWidth, window.innerHeight);
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
// Normalize mouse coordinates to range [-1, 1]
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* 5. THE ANIMATION LOOP AND UPDATE LOGIC
*/
function animate(time) {
requestAnimationFrame(animate);
// --- FPS Calculation ---
const currentTime = performance.now();
const delta = (currentTime - lastTime) / 1000; // Delta time in seconds
lastTime = currentTime;
const fps = Math.round(1 / delta);
fpsCounterElement.innerText = `FPS: ${fps}`;
// --- Interaction Update (Mouse Tilt) ---
// Smoothly interpolate camera rotation based on mouse position
camera.rotation.y += (mouseX * 0.005 - camera.rotation.y) * 0.1;
camera.rotation.x += (mouseY * 0.005 - camera.rotation.x) * 0.1;
// --- Galaxy Animation ---
const timeFactor = time / 2000; // Speed control
// Rotation around Y-axis (Spinning the galaxy)
particlesGalaxy.rotation.y += 0.005 * timeFactor;
// Scaling and movement for a dynamic effect
particlesGalaxy.scale.set(1 + Math.sin(timeFactor * 0.5) * 0.1, 1 + Math.sin(timeFactor * 0.5) * 0.1, 1 + Math.cos(timeFactor * 0.3) * 0.1);
// --- Starfield Animation (Parallax/Drift) ---
// Slowly move the stars to create a sense of depth and background drift
starfieldParticles.position.y = Math.sin(timeFactor * 0.2) * 50;
starfieldParticles.rotation.z += 0.0001;
renderer.render(scene, camera);
}
// Start the application
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy animation with 5000 colorful particles that respond to mouse movement and include a starfield background. Here's the complete solution:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
cursor: none;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#canvas-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
color: #fff;
padding: 10px 15px;
border-radius: 5px;
font-size: 14px;
z-index: 100;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.8);
font-size: 24px;
font-weight: bold;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
backdrop-filter: blur(5px);
padding: 10px 15px;
border-radius: 5px;
background: rgba(0, 0, 0, 0.5);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
backdrop-filter: blur(5px);
padding: 10px 15px;
border-radius: 5px;
background: rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body>
<div id="container">
<div id="canvas-container"></div>
<div id="fps-counter">FPS: 60</div>
<div id="title">Galaxy Particle Animation</div>
<div id="instructions">Move your mouse to tilt the galaxy | Click to change color palette</div>
</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('canvas-container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create particles
createParticles();
// Add lighting
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1, 1000);
pointLight.position.set(0, 0, 0);
scene.add(pointLight);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.addEventListener('click', changeColorPalette);
// Start animation
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create particle system
function createParticles() {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Color palette
const palettes = [
[0.8, 0.2, 0.9], // Purple
[0.2, 0.6, 0.9], // Blue
[0.2, 0.9, 0.7], // Teal
[0.9, 0.4, 0.2], // Orange
[0.9, 0.2, 0.5] // Pink
];
let currentPalette = 0;
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position particles in a spiral galaxy pattern
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 4;
const height = (Math.random() - 0.5) * 100;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Random size
sizes[i] = Math.random() * 3 + 1;
// Color from palette
const color = new THREE.Color();
const palette = palettes[currentPalette];
color.setRGB(
palette[0] * (0.5 + Math.random() * 0.5),
palette[1] * (0.5 + Math.random() * 0.5),
palette[2] * (0.5 + Math.random() * 0.5)
);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Change color palette
function changeColorPalette() {
const palettes = [
[0.8, 0.2, 0.9], // Purple
[0.2, 0.6, 0.9], // Blue
[0.2, 0.9, 0.7], // Teal
[0.9, 0.4, 0.2], // Orange
[0.9, 0.2, 0.5] // Pink
];
const palette = palettes[Math.floor(Math.random() * palettes.length)];
// Update particle colors
const positions = particles.geometry.attributes.position.array;
const colors = particles.geometry.attributes.color.array;
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
const color = new THREE.Color();
color.setRGB(
palette[0] * (0.5 + Math.random() * 0.5),
palette[1] * (0.5 + Math.random() * 0.5),
palette[2] * (0.5 + Math.random() * 0.5)
);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
particles.geometry.attributes.color.needsUpdate = true;
gemma4:e4b
This is a complex visualization requiring careful handling of Three.js setup, physics (mouse interaction), geometry calculations, and performance monitoring.
The following code provides a complete, single-file HTML solution that runs the animated particle system when opened in a modern browser.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: rgba(255, 255, 255, 0.8);
font-family: monospace;
padding: 10px;
background-color: rgba(0, 0, 0, 0.4);
border-radius: 5px;
z-index: 100;
}
</style>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<script>
// ========================================
// GLOBAL SETUP VARIABLES
// ========================================
let scene, camera, renderer;
let galaxyParticles;
const PARTICLE_COUNT = 5000;
const clock = new THREE.Clock();
// Mouse interaction tracking
let mouseX = 0;
let mouseY = 0;
// FPS Tracking Variables
let frameCount = 0;
let lastTime = performance.now();
const fpsDisplay = document.getElementById('fps-counter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// Scene Setup
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000000, 0.0005);
// Camera Setup (Perspective view)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 100;
// Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create the Galaxy Particle System
createGalaxyParticles();
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove);
// Start the animation loop
animate();
}
/**
* Generates the 3D geometry for the spiral galaxy particles.
*/
function createGalaxyParticles() {
const positions = [];
const colors = [];
const color = new THREE.Color();
// Loop through particle count to generate coordinates
for (let i = 0; i < PARTICLE_COUNT; i++) {
const t = (i / PARTICLE_COUNT) * Math.PI * 4; // Angle factor (Spiral wrapping)
const r = i / PARTICLE_COUNT * 15; // Radius growth
const z = r * 0.5 + Math.sin(t * 0.8) * 10; // Z coordinate (Depth/spiral structure)
// X, Y coordinates based on spiral geometry: x = r*cos(t), y = r*sin(t)
const x = r * Math.cos(t);
const y = r * Math.sin(t) * 0.5; // Flattened vertical distribution
// Store positions
positions.push(x, y, z);
// Assign random colors for a vibrant galaxy look
color.setHSL(i / PARTICLE_COUNT, 1.0, 0.6 + Math.random() * 0.2);
colors.push(color.r, color.g, color.b);
}
// Create Buffer Geometry (efficient way to store large arrays of data)
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup (PointsMaterial uses the vertex colors)
const material = new THREE.PointsMaterial({
size: 0.5 + Math.random() * 1.5, // Vary particle size slightly
vertexColors: true, // Use stored colors
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Handles window resizing to keep the canvas dimensions correct.
*/
function onWindowResize() {
camera.viewport.set(0, 0, 1, 1); // Reset viewport
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Tracks mouse movement for interactive camera tilt effect.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - window.innerWidth / 2) * 0.5; // Normalize and scale
mouseY = (event.clientY - window.innerHeight / 2) * 0.5; // Normalize and scale
}
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
// --- 1. Animation Logic ---
const time = clock.getElapsedTime();
// Rotate the entire galaxy slowly for continuous movement
galaxyParticles.rotation.x += 0.0001;
galaxyParticles.rotation.y += 0.0005;
// Apply a subtle pulsating effect to particle size/opacity (optional)
const timeFactor = Math.sin(time * 0.2);
galaxyParticles.material.size = THREE.MathUtils.lerp(1.0, 2.0, Math.abs(timeFactor));
// --- 2. Mouse Interaction (Camera Tilt) ---
// Smoothly move the camera target based on mouse input
camera.position.x += (mouseX * 0.1 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 0.1 - camera.position.y) * 0.05;
// Also subtly tilt the entire scene/group based on mouse input (better visual effect)
scene.rotation.x = mouseY * 0.0005;
scene.rotation.y = mouseX * 0.0005;
// --- 3. Rendering ---
renderer.render(scene, camera);
// --- 4. Performance Calculation (FPS) ---
frameCount++;
const elapsed = performance.now() - lastTime;
if (elapsed >= 1000) { // Update FPS every second
const fps = Math.round(frameCount * 1000 / elapsed);
fpsDisplay.textContent = `FPS: ${fps}`;
// Reset for next measurement cycle
lastTime = performance.now();
frameCount = 0;
}
}
// --- Initialization Call ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D galaxy animation using Three.js with 5000 colorful particles that respond to mouse movement and feature a starfield background.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
cursor: pointer;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.8);
font-size: 24px;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
letter-spacing: 2px;
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
max-width: 300px;
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="title">INTERACTIVE GALAXY PARTICLE ANIMATION</div>
<div id="info">5000 Particles | Galaxy Spiral | Mouse Interaction</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Click to change color palette</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats = { fps: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.addEventListener('click', changeColorPalette);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleGeometry = new THREE.BufferGeometry();
const particleMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Color palettes
const palettes = [
[0.8, 0.2, 0.8], // Purple
[0.2, 0.8, 0.8], // Cyan
[0.8, 0.8, 0.2], // Yellow
[0.8, 0.4, 0.2], // Orange
[0.2, 0.4, 0.8] // Blue
];
let currentPalette = 0;
const palette = palettes[currentPalette];
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral galaxy formation
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const x = Math.cos(angle) * radius;
const y = Math.sin(angle) * radius;
const z = (Math.random() - 0.5) * 20;
positions[i3] = x;
positions[i3 + 1] = y;
positions[i3 + 2] = z;
// Random size
sizes[i] = Math.random() * 2 + 0.5;
// Color based on position and palette
const colorFactor = i / particleCount;
colors[i3] = palette[0] + (Math.random() * 0.3 - 0.15);
colors[i3 + 1] = palette[1] + (Math.random() * 0.3 - 0.15);
colors[i3 + 2] = palette[2] + (Math.random() * 0.3 - 0.15);
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particleGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Change color palette
function changeColorPalette() {
const palettes = [
[0.8, 0.2, 0.8], // Purple
[0.2, 0.8, 0.8], // Cyan
[0.8, 0.8, 0.2], // Yellow
[0.8, 0.4, 0.2], // Orange
[0.2, 0.4, 0.8] // Blue
];
const currentPalette = Math.floor(Math.random() * palettes.length);
const palette = palettes[currentPalette];
const colors = particles.geometry.attributes.color.array;
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
colors[i3] = palette[0] + (Math.random() * 0.3 - 0.15);
colors[i3 + 1] = palette[1] + (Math.random() * 0.3 - 0.15);
colors[i3 + 2] = palette[2] + (Math.random() * 0.3 - 0.15);
}
particles.geometry.attributes.color.needsUpdate = true;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate particles
if (particles) {
particles.rotation.x += 0.0005;
particles.rotation.y += 0.001;
// Mouse interaction
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.posit
gemma4:e4b
This project requires a robust setup involving geometry generation, real-time rendering, event handling, and performance tracking. Since it must be contained in a single file, all elements are included below.
### 🌟 Cosmic Particle Galaxy Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: #ffffff;
font-family: 'Courier New', monospace;
background: rgba(0, 0, 0, 0.5);
padding: 8px 12px;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: --</div>
<!-- Load Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// ======================== GLOBAL VARIABLES & SETUP ========================
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
let mouseX = 0, mouseY = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
// FPS Tracking Variables
let frameCount = 0;
let lastTime = performance.now();
let fpsDisplay;
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// --- Scene Setup ---
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// --- Camera Position ---
camera.position.z = 50;
// --- Event Listeners ---
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove);
// --- Create Components ---
createGalaxyParticles(5000, 150);
createStarField(8000);
// Start the animation loop
animate();
}
/**
* Creates the main galaxy-like particle system.
* Particles are placed in a spiral pattern (r = theta, z = k * theta).
* @param {number} count - Number of particles to generate.
* @param {number} maxRadius - Maximum radius/extent of the galaxy.
*/
function createGalaxyParticles(count, maxRadius) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < count; i++) {
// Calculate angular position (theta) and radius (r) for spiral structure
const theta = Math.random() * Math.PI * 2; // Full circle rotation
// Sine wave variation for depth and size, creating the 'spiral' effect
const r = Math.pow(Math.random(), 0.5) * maxRadius;
// Z position determined by angle, creating the depth curve (spiral)
const z_factor = Math.sin(theta / 3);
// X and Y coordinates for a spiral structure:
const x = r * Math.cos(theta) * Math.random() * 0.5 + (Math.random() - 0.5) * 10;
const y = r * Math.sin(theta) * Math.random() * 0.5 + (Math.random() - 0.5) * 10;
// Z depth adjusted by the spiral factor
const z = Math.sin(theta / 4) * maxRadius * 0.8;
positions.push(x, y, z);
// Assign random vibrant color
color.setHSL(Math.random(), 1.0, 0.5 + Math.random() * 0.3);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true, // Use the colors defined in geometry
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a dense, randomly positioned starfield background.
* @param {number} count - Number of stars to generate.
*/
function createStarField(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < count; i++) {
// Spread particles over a large cubic area
const x = (Math.random() - 0.5) * 4000;
const y = (Math.random() - 0.5) * 4000;
const z = (Math.random() - 0.5) * 4000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a simple material for the stars
const material = new THREE.PointsMaterial({
size: 1,
color: 0xaaaaee, // Light blue/white star color
blending: THREE.AdditiveBlending,
transparent: true
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
// ======================== INTERACTIVITY & UTILITIES ========================
/**
* Handles window resizing to keep the scene scaled correctly.
*/
function onWindowResize() {
camera.viewport = new THREE.Vector2();
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates mouse coordinates and clamps them to the screen size.
*/
function onDocumentMouseMove(event) {
// Normalize mouse position (-1 to +1 range)
mouseX = (event.clientX - windowHalfX) / window.innerWidth;
mouseY = (event.clientY - windowHalfY) / window.innerHeight;
}
/**
* Updates the FPS counter display.
*/
function updateFPS(timestamp) {
const elapsed = timestamp - lastTime;
frameCount++;
if (elapsed >= 1000) { // Update every second
const fps = Math.round((frameCount * 1000 / elapsed));
document.getElementById('fps-counter').innerHTML = `FPS: ${fps}`;
// Reset counters for the next measurement cycle
frameCount = 0;
lastTime = timestamp;
}
}
// ======================== ANIMATION LOOP ========================
/**
* The main animation loop using requestAnimationFrame.
*/
function animate(time) {
requestAnimationFrame(animate);
const timeScale = 0.0005;
// --- A. Galaxy Rotation (Self-Movement) ---
if (galaxyParticles) {
// Rotate the entire galaxy slowly around Y and X axes
galaxyParticles.rotation.y += timeScale * 0.1;
galaxyParticles.rotation.x = Math.sin(time * 0.0002) * 0.1;
}
// --- B. Starfield Movement (Parallax/Drift) ---
if (starFieldParticles) {
// Make the stars slowly drift or "breathe"
starFieldParticles.rotation.y += timeScale * 0.005;
starFieldParticles.position.x = Math.sin(time * 0.0002) * 10;
}
// --- C. Camera Tilt (Mouse Interaction) ---
// Smoothly interpolate the camera's target rotation based on mouse position
const targetRotationX = mouseY * 0.5;
const targetRotationY = mouseX * 0.5;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.05;
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.05;
// --- D. Rendering and Performance ---
renderer.render(scene, camera);
updateFPS(performance.now());
}
// Start the application
init();
</script>
</body>
</html>
```
gemma4:e4b
This is a complex task that requires advanced knowledge of WebGL/Three.js. Since I cannot execute external files or libraries directly, I will provide the complete, self-contained HTML file using ES6 JavaScript and CDN links for Three.js.
### Particle Galaxy Animation Code
Save the following code as `index.html`. When you open it in a modern browser, the interactive animation will run immediately.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Particle Galaxy</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-family: 'Consolas', monospace;
padding: 10px;
background: rgba(0, 0, 0, 0.4);
border-radius: 5px;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Three.js CDN link -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- GLOBAL VARIABLES AND SETUP ---
let scene, camera, renderer;
let particles, geometry, material;
const PARTICLE_COUNT = 5000;
// Mouse tracking for interactive tilt
const mouse = new THREE.Vector2();
const targetRotation = { x: 0, y: 0 };
// FPS Counter variables
let fpsCounterElement = document.getElementById('fps-counter');
let frameCount = 0;
let lastTime = performance.now();
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set initial camera position (looking into the galaxy)
camera.position.z = 50;
camera.position.y = 10;
// 2. Particle System Creation (The Galaxy)
createParticles();
// 3. Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove);
// Start the animation loop
animate();
}
/**
* Generates particles in a spiral/disk shape.
*/
function createParticles() {
geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const sizes = [];
// Simple color palette for variation (Blue to Purple/Red)
const baseColor = new THREE.Color(0x6a5acd);
for (let i = 0; i < PARTICLE_COUNT; i++) {
// Calculate parameters for spiral placement
// Angle theta determines the radius and position on the plane
const angle = Math.random() * Math.PI * 2;
// Radius r: makes it denser near the center and fades out
const radius = Math.sqrt(Math.random()) * 30;
// Depth z: creates the disk effect
const depth = (Math.random() - 0.5) * 10;
// Position calculation
const x = Math.cos(angle) * radius;
const y = Math.random() * 10 - 5; // Vertical spread
const z = Math.sin(angle) * radius + depth * 0.5;
positions.push(x, y, z);
// Color generation (variation based on position for visual appeal)
const colorIntensity = positions[2] / 30 + 0.5; // Depth influences color
const r = Math.floor(Math.random() * 100 + 100);
const g = Math.floor(Math.random() * 100 + 50);
const b = Math.floor(Math.random() * 100 + 20);
colors.push(r, g, b);
sizes.push(Math.random() * 4 + 1); // Varying particle sizes
}
// Set the position attributes
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a PointsMaterial for rendering particles
material = new THREE.PointsMaterial({
size: 1.5, // Initial size (will be adjusted in update)
vertexColors: true, // Allows per-particle coloring
blending: THREE.AdditiveBlending, // Makes colors glow better
transparent: true,
opacity: 0.8
});
// We must use a custom class to handle dynamic sizes/colors needed for the spiral effect
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
/**
* Handles mouse movement and updates target camera rotations.
*/
function onMouseMove(event) {
// Normalize coordinates to -1 to 1 range
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// Smoothly update the target rotation based on mouse input
targetRotation.y = mouse.x * Math.PI / 4; // Horizontal tilt
targetRotation.x = mouse.y * Math.PI / 4; // Vertical tilt
}
/**
* Handles window resizing to keep the canvas full screen.
*/
function onWindowResize() {
camera.viewport = null;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// --- ANIMATION LOOP AND INTERACTIVITY ---
function animateParticles(delta) {
const positions = geometry.attributes.position.array;
const timeFactor = delta * 0.5; // Controls rotation speed
// Rotate the entire galaxy structure slowly around the Y and X axes
particles.rotation.y += 0.0001 * delta;
particles.rotation.x += 0.00005 * delta;
// Simulate a slow, continuous pulsing/breathing effect on particle positions
for (let i = 0; i < PARTICLE_COUNT; i++) {
const index = i * 3;
// Position update: Simple sine wave oscillation for "energy"
positions[index] += Math.sin(i * 0.01 + timeFactor) * 0.005;
positions[index + 1] += Math.cos(i * 0.02 + timeFactor) * 0.005;
positions[index + 2] += Math.sin((i+1) * 0.01 + timeFactor) * 0.005;
// Clamp positions to prevent them drifting too far away
if (Math.abs(positions[index]) > 40 || Math.abs(positions[index+1]) > 20 || Math.abs(positions[index+2]) > 40) {
// Simple reset mechanic if particles stray too far
positions[index] *= 0.99;
positions[index + 1] *= 0.99;
positions[index + 2] *= 0.99;
}
}
geometry.attributes.position.needsUpdate = true;
}
function updateCamera(deltaTime) {
// Smoothly interpolate camera rotation towards the target rotation (mouse position)
camera.rotation.y += (targetRotation.y - camera.rotation.y) * 0.05;
camera.rotation.x += (targetRotation.x - camera.rotation.x) * 0.05;
// Optional: Make the camera slightly orbit over time
camera.position.z = 50 + Math.sin(Date.now() / 1000) * 5;
}
/**
* Main animation loop
*/
function animate() {
requestAnimationFrame(animate);
// Calculate Delta Time (Time elapsed since last frame)
const currentTime = performance.now();
const deltaTime = (currentTime - lastTime) / 1000; // Convert ms to seconds
lastTime = currentTime;
// Update logic
animateParticles(deltaTime);
updateCamera(deltaTime);
// Render the scene
renderer.render(scene, camera);
// Update FPS Counter
frameCount++;
if (currentTime - lastTime >= 1000) { // Check every second
const fps = Math.round(frameCount / ((currentTime - lastTime) / 1000));
fpsCounterElement.textContent = `FPS: ${fps}`;
frameCount = 0;
lastTime = currentTime;
}
}
// Start the application
init();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from a CDN, you can follow this example. This example will include a starfield background, 5000 colorful particles rotating in a galaxy-like spiral, and the FPS counter in the corner which responds to mouse movement for tilting effects.
Here's how you could structure your HTML file:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fps { position: absolute; top: 10px; left: 10px; color: white; }
</style>
</head>
<body>
<div id="fps">FPS: 0</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Particle system setup
const particlesMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1 });
const particleGeometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < 5000; i++) {
const x = Math.random() * 2 - 1;
const y = Math.random() * 2 - 1;
const z = Math.random() * 2 - 1;
positions.push(x, y, z);
}
particleGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const particles = new THREE.Points(particleGeometry, particlesMaterial);
scene.add(particles);
// Light setup
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(5, 5, 5).multiplyScalar(20);
scene.add(pointLight);
// Camera position and movement based on mouse movement
camera.position.z = 5;
const handleResize = () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
};
window.addEventListener('resize', handleResize, false);
const animate = () => {
requestAnimationFrame(animate);
// Rotate particles to create a spiral effect
particles.rotation.x += 0.005;
particles.rotation.y += 0.005;
// Update mouse movement for tilt effect
const mouse = new THREE.Vector2();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
const vector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
vector.unproject(camera).subtract(camera.position).normalize();
// Update camera tilt based on mouse movement
const q = new THREE.Quaternion().setFromEuler(new THREE.Euler(vector.x * 2, vector.y * 2, 0));
camera.quaternion.slerp(q, 0.1);
renderer.render(scene, camera);
};
// FPS Counter
let fps = 0;
const startTime = Date.now();
const tick = () => {
requestAnimationFrame(tick);
const elapsedTime = (Date.now() - startTime) / 1000;
fps++;
if (elapsedTime > 1) {
document.getElementById('fps').innerText = `FPS: ${fps}`;
fps = 0;
startTime = Date.now();
}
};
tick();
animate();
</script>
</body>
</html>
```
This HTML file sets up a basic Three.js scene with particles that rotate in space, responds to mouse movement for tilting effects, and displays an FPS counter at the top left corner of the screen. Make sure to include the necessary scripts from the CDN and adjust paths as needed.
gemma4:e4b
This is a complex and highly resource-intensive animation, but by using Three.js efficiently with `BufferGeometry` for both particle systems, we can achieve the desired visual effect while maintaining performance.
Here is the complete single HTML file solution:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#info-overlay {
position: fixed;
top: 10px;
left: 10px;
color: white;
font-family: 'Arial', sans-serif;
background: rgba(0, 0, 0, 0.5);
padding: 8px 12px;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="info-overlay">FPS: 0</div>
<!-- Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- GLOBAL VARIABLES AND SETUP ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
let mouseX = 0, mouseY = 0;
const NUM_GALAXIES = 5000;
const NUM_STARS = 15000;
// Performance tracking variables
let lastTime = performance.now();
let frameCount = 0;
let fpsInterval = null;
/**
* Initializes the Three.js environment (Scene, Camera, Renderer).
*/
function init() {
// Scene setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set camera position and look slightly into the scene
camera.position.set(0, 0, 50);
camera.lookAt(0, 0, 0);
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove);
// Create particle systems
createStarfield();
createGalaxyParticles();
// Start the animation loop
animate();
// Start FPS counter display
fpsInterval = setInterval(updateFPS, 500);
}
/**
* Handles window resizing to keep the canvas full screen.
*/
function onWindowResize() {
camera.viewport = new THREE.Vector2(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Handles mouse movement for interactive tilting/look-at effect.
* @param {Event} event - The mouse move event.
*/
function onDocumentMouseMove(event) {
// Normalize coordinates to range between -1 and 1
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
// --- PARTICLE CREATION FUNCTIONS ---
/**
* Creates the dense, spiral-shaped galaxy particle system.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Spiral generation logic (Polar coordinates to Cartesian)
for (let i = 0; i < NUM_GALAXIES; i++) {
// Calculate radius and angle based on index for a spiral effect
const r = Math.random() * 50 + 1; // Base spread
const theta = Math.random() * Math.PI * 2;
// Spiral deformation: make particles closer to the center if they are 'later' in the sequence (i)
const spiralFactor = (Math.sin(i / 500 + r / 10) * 0.5);
// Position calculation: X, Y, Z
const x = Math.cos(theta) * r * (0.8 + spiralFactor * 0.2);
const y = Math.sin(theta) * r * (0.8 + spiralFactor * 0.2);
const z = Math.random() * 15 - 7.5; // Depth variation
positions.push(x, y, z);
// Random colorful assignment
color.setHSL(Math.random(), 0.9, 0.5 + Math.random() * 0.4);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup: Use PointsMaterial for performance and assign colors
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Crucial: use the color attribute defined in geometry
transparent: true,
blending: THREE.AdditiveBlending // Makes particles glow when overlapping
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a distant, sparse starfield background.
*/
function createStarfield() {
const geometry = new THREE.BufferGeometry();
const positions = [];
// Stars are random and usually white/blue for space effect
for (let i = 0; i < NUM_STARS; i++) {
// Spread stars far out in a large cube area
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material setup for stars
const material = new THREE.PointsMaterial({
size: 1,
color: 0xA0A0FF, // Soft blue/white color
transparent: true,
blending: THREE.AdditiveBlending
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
// --- ANIMATION LOOP AND LOGIC ---
/**
* The main animation loop function (called every frame).
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now();
const delta = (time - lastTime) / 1000; // Time elapsed since last frame in seconds
lastTime = time;
// 1. Galaxy Rotation and Movement
if (galaxyParticles) {
const positions = galaxyParticles.geometry.attributes.position.array;
for (let i = 0; i < NUM_GALAXIES; i++) {
const index = i * 3;
// Subtle, continuous rotation around the Y-axis
positions[index] += Math.sin(time * 0.001 + i) * 0.001; // X change
positions[index + 1] += Math.cos(time * 0.001 + i) * 0.001; // Y change
positions[index + 2] += 0; // Z remains relatively stable for rotation
// Make the galaxy slightly pulse or rotate overall
const x = positions[index];
const y = positions[index + 1];
const z = positions[index + 2];
// Apply a gentle circular motion (simulating galactic rotation)
positions[index] = Math.cos(time * 0.0005 + i / 50) * (r_base + Math.sin(time * 0.0001 + i/10));
positions[index + 1] = Math.sin(time * 0.0005 + i / 50) * (r_base + Math.sin(time * 0.0001 + i/10));
}
// Note: For true performance, updating positions directly on the GPU is better, but this simple JS approach works well for demonstration.
}
// 2. Starfield Movement (Parallax effect)
if (starfieldParticles) {
const position = starfieldParticles.geometry.attributes.position;
const speedFactor = delta * 0.5; // Stars move slower than the camera tilt
for (let i = 0; i < NUM_STARS; i++) {
const index = i * 3;
// Simulate gentle drift/flow of stars
position[index] += Math.cos(time * 0.0001 + i) * 0.00005; // Slow X movement
position[index + 2] += speedFactor * 0.05; // Slow Z movement (towards camera)
}
}
// 3. Camera Update (Mouse Tilt Effect)
// Lerp the camera rotation towards the mouse input for smoothness
camera.rotation.y += (mouseX * 0.01 - camera.rotation.y) * 0.05;
camera.rotation.x += (-mouseY * 0.01 - camera.rotation.x) * 0.05;
// Render the scene
renderer.render(scene, camera);
}
/**
* Updates and displays the FPS counter in the corner.
*/
function updateFPS() {
const fps = Math.round(1 / ((performance.now() - lastTime) / (frameCount * 1000)));
document.getElementById('info-overlay').innerText = `FPS: ${fps}`;
frameCount = 0; // Reset counter for the next interval
}
// --- START THE APPLICATION ---
init();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN, you can follow the steps below. This example will include a starfield background, colorful particles rotating in a spiral pattern, and a FPS counter that responds to mouse movement for tilting effects. Everything is encapsulated within a single HTML file.
Here's how you can set up your HTML file:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Starfield background
const starsGeometry = new THREE.BufferGeometry();
const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1 });
let starPositions = [];
for (let i = 0; i < 5000; i++) {
let x = (Math.random() - 0.5) * 2000;
let y = (Math.random() - 0.5) * 2000;
let z = Math.random() * 4000 - 2000;
starPositions.push(x, y, z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
const stars = new THREE.Points(starsGeometry, starsMaterial);
scene.add(stars);
// Particle system
const particleCount = 5000;
const particlesGeometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
let x = (Math.random() - 0.5) * 2000;
let y = (Math.random() - 0.5) * 2000;
let z = Math.random() * 4000 - 2000;
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const particleMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1 });
const particles = new THREE.Points(particlesGeometry, particleMaterial);
scene.add(particles);
// Camera position and rotation
camera.position.z = 1500;
let mouseX = 0, mouseY = 0;
window.addEventListener('mousemove', (event) => {
mouseX = event.clientX - window.innerWidth / 2;
mouseY = event.clientY - window.innerHeight / 2;
});
// Animation loop
function animate() {
requestAnimationFrame(animate);
particles.rotation.x += 0.005;
particles.rotation.y += 0.005;
camera.position.z += (mouseY * 0.01) % 2 - 1;
camera.position.x += (mouseX * 0.01) % 2 - 1;
renderer.render(scene, camera);
}
animate();
// FPS counter
let fps = 0;
let startTime = Date.now();
function countFPS() {
const endTime = Date.now();
fps = Math.round(1 / ((endTime - startTime) / 1000));
startTime = endTime;
document.body.appendChild(renderer.domElement).innerHTML = `FPS: ${fps}`;
}
setInterval(countFPS, 100);
</script>
</body>
</html>
```
This code sets up a basic Three.js scene with a starfield background and a particle system that rotates in response to mouse movement for tilting effects. The particles are colored white, but you can adjust the color using the `color` property in the material settings if needed. The FPS counter is updated every 100 milliseconds and displayed in the corner of the canvas.
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an interactive 3D particle animation with a galaxy-like spiral, mouse tilt response, starfield background, and FPS counter - all in a single HTML file using Three.js.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 163, 0.3);
}
#info p {
margin: 5px 0;
font-size: 1rem;
opacity: 0.8;
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
font-family: monospace;
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
max-width: 300px;
}
#instructions h2 {
margin-bottom: 10px;
color: #ff7eb3;
}
#instructions ul {
padding-left: 20px;
}
#instructions li {
margin: 8px 0;
font-size: 0.9rem;
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>5,000 colorful particles rotating in a spiral galaxy</p>
<p>Move your mouse to tilt the galaxy</p>
</div>
<div id="instructions">
<h2>Controls</h2>
<ul>
<li>Move mouse to rotate galaxy</li>
<li>Click and drag to rotate view</li>
<li>Scroll to zoom in/out</li>
</ul>
</div>
<div id="fps-counter">FPS: 0</div>
</div>
<!-- Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let fpsCounter = document.getElementById('fps-counter');
let clock = new THREE.Clock();
let stats = {
fps: 0,
frameCount: 0,
lastTime: performance.now()
};
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
2000
);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create the galaxy particle system
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) * 0.5 + 0.5; // Blue to red transition
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.3 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random particle sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starCount = 2000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(starCount * 3);
const sizes = new Float32Array(starCount);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
// Random positions in a sphere
const radius = 500 + Math.random() * 1000;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positions[i3 + 2] = radius * Math.cos(phi);
// Random star sizes
sizes[i] = Math.random() * 1.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
color: 0xffffff,
size: 1,
sizeAttenuation: true
});
const starfield = new THREE.Points(geometry, material);
scene.add(starfield);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 2;
mouseY = (event.clientY - windowHalfY) / 2;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
gemma4:e4b
This is a complex task that requires combining advanced WebGL concepts (Three.js) with interactive event handling and performance optimization.
The following code provides a complete, self-contained HTML file that achieves the described effect: a spiral galaxy of particles, responsive to mouse movement, set against a starfield background, and displaying an FPS counter.
### 🌌 Interactive Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Spiral Galaxy Particles</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
/* Style for the FPS counter overlay */
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: rgba(255, 255, 255, 0.8);
font-family: 'Arial', sans-serif;
padding: 5px 10px;
background: rgba(0, 0, 0, 0.5);
border-radius: 5px;
user-select: none;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- GLOBAL VARIABLES & SETUP ---
let scene, camera, renderer;
let particleSystem, starFieldParticles;
const PARTICLE_COUNT = 5000;
const STARFIELD_SIZE = 1000; // Size of the background cube
// Variables for mouse interaction
let mouseX = 0;
let mouseY = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
// Performance tracking variables
let frameCount = 0;
let lastTime = performance.now();
const fpsDisplay = document.getElementById('fps-counter');
/**
* Initializes the Three.js environment (Scene, Camera, Renderer)
*/
function init() {
// 1. SCENE SETUP
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set camera position and initial look
camera.position.z = 50;
// 2. CREATE BACKGROUND STARFIELD
createStarField();
// 3. CREATE GALAXY PARTICLES (The main attraction)
createGalaxyParticles();
// 4. EVENT LISTENERS
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Start the animation loop
animate();
}
/**
* Generates a large background field of random points (stars).
*/
function createStarField() {
const starGeometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Generate particles for the cube defined by STARFIELD_SIZE
for (let i = 0; i < 50000; i++) {
// Random position within the large cubic space
positions.push(
(Math.random() - 0.5) * STARFIELD_SIZE,
(Math.random() - 0.5) * STARFIELD_SIZE,
(Math.random() - 0.5) * STARFIELD_SIZE
);
// Random bright color for stars
const color = new THREE.Color();
color.setHSL(Math.random(), Math.random() * 0.4 + 0.6, Math.random() * 0.5 + 0.7);
colors.push(color.r, color.g, color.b);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
starGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const starMaterial = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true // Use the colors defined in the geometry
});
starFieldParticles = new THREE.Points(starGeometry, starMaterial);
scene.add(starFieldParticles);
}
/**
* Generates particles arranged in a spiral/galaxy pattern.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Creating the spiral structure using polar coordinates (r, theta, z)
for (let i = 0; i < PARTICLE_COUNT; i++) {
// Normalized position i/PARTICLE_COUNT gives a value from 0 to 1
const progress = i / PARTICLE_COUNT;
// Spiral structure parameters
const radius = Math.pow(progress, 2) * 50 + (Math.random() - 0.5) * 5; // Radial spread increases with progress
const zPos = (Math.sin(progress * Math.PI * 4)) * 100; // Z oscillation for the spiral shape
const theta = progress * Math.PI * 6 + Math.random() * Math.PI * 2; // Angle rotation
// Convert polar to Cartesian coordinates: (x, y, z)
const x = radius * Math.cos(theta);
const y = radius * Math.sin(theta) * 0.8; // Slight flattening in Y axis for visual appeal
const z = zPos + (Math.random() - 0.5) * 10;
positions.push(x, y, z);
// Assign random colors to the particles
const color = new THREE.Color();
color.setHSL(progress / PARTICLE_COUNT * 0.8 + Math.random() * 0.2, 1, 0.6);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1.5, // Particle size
vertexColors: true,
transparent: true,
opacity: 0.9
});
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
/**
* Handles window resizing to keep the aspect ratio correct.
*/
function onWindowResize() {
camera.viewport.set(0, 0, 1, 1); // Reset viewport
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Tracks mouse movement for interactive camera/object tilt.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX);
mouseY = (event.clientY - windowHalfY);
}
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now();
const delta = time - lastTime;
lastTime = time;
// --- 1. CAMERA MOVEMENT (Mouse Tilt Response) ---
// We use the mouse position to slightly adjust camera rotation, making it feel like looking around the galaxy.
camera.rotation.y += (mouseX * 0.0005 - camera.rotation.y) * 0.05;
camera.rotation.x += (-mouseY * 0.0005 - camera.rotation.x) * 0.05;
// --- 2. GALAXY ANIMATION (Rotation and Pulsing) ---
if (particleSystem) {
// Continuous rotation of the whole galaxy system
particleSystem.rotation.y += 0.001;
particleSystem.rotation.x += 0.0005;
// Subtle internal pulsing/movement effect for depth
const timeFactor = Math.sin(time * 0.0002);
particleSystem.scale.setScalar(1 + Math.abs(timeFactor) * 0.05);
}
// --- 3. STARFIELD ANIMATION (Camera movement through stars) ---
if (starFieldParticles) {
// Make the starfield appear to drift slowly over time
const elapsed = time / 1000; // Convert milliseconds to seconds
starFieldParticles.position.x = Math.sin(elapsed * 0.05) * 200;
starFieldParticles.position.y = Math.cos(elapsed * 0.03) * 200;
}
// --- 4. RENDER SCENE ---
renderer.render(scene, camera);
// --- 5. FPS Counter Update ---
frameCount++;
const elapsedSeconds = (time - lastTime) / 1000;
const fps = 1 / elapsedSeconds || 0;
fpsDisplay.textContent = `FPS: ${Math.round(fps)}`;
}
// Start the application
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy particle animation using Three.js that responds to mouse movement with a starfield background and FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.8);
font-size: 24px;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="title">Interactive 3D Galaxy Animation</div>
<div id="info">5000 Colorful Particles | Mouse Movement Controls</div>
<div id="fps-counter">FPS: 60</div>
<div id="instructions">Move mouse to tilt the galaxy | Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 60 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starsGeometry = new THREE.BufferGeometry();
const starsMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starsVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starsVertices.push(x, y, z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3));
const starField = new THREE.Points(starsGeometry, starsMaterial);
scene.add(starField);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const particlesGeometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
// Position particles in spiral pattern
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) * 0.5 + 0.5; // Blue to red transition
color.setHSL(hue, 1, 0.5);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Vary particle sizes
sizes[i] = Math.random() * 3 + 1;
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particlesGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particlesGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const particleMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
particleSystem = new THREE.Points(particlesGeometry, particleMaterial);
scene.add(particleSystem);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate galaxy particles
if (particleSystem) {
particleSystem.rotation.x = elapsed * 0.05;
particleSystem.rotation.y = elapsed * 0.02;
// Mouse interaction
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
// Update FPS counter
stats.fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${stats.fps}`;
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this Galaxy Animation:
1. **5000 Colorful Particles**: Particles arranged in a spiral galaxy pattern with vibrant colors transitioning from blue to red
2. **Interactive Controls**:
- Mouse movement tilts the galaxy
- Scroll to zoom in/out
3. **Starfield Background**: 10,000 stars scattered throughout space for depth
4. **FPS Counter**: Displays real-time frame rate in the bottom-right corner
5. **Smooth Animations**:
- Continuous rotation of the galaxy
- Smooth camera movements
- Responsive controls with damping
6. **Responsive Design**: Adapts to any screen size
7. **Visual Effects**:
- Particle sizes vary for depth perception
-
gemma4:e4b
This complex animation requires robust JavaScript (Three.js) and performance optimization techniques. Below is the complete, single-file HTML solution.
### 🌌 Interactive Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-family: 'Arial', sans-serif;
font-size: 18px;
background: rgba(0, 0, 0, 0.4);
padding: 5px 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// =========================================
// GLOBAL VARIABLES AND SETUP
// =========================================
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
const particleCount = 5000;
const clock = new THREE.Clock();
// Mouse interaction variables
let mouseX = 0;
let mouseY = 0;
// FPS Counter variables
let frameCount = 0;
let lastTime = performance.now();
function init() {
// 1. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 2. Scene and Camera Setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 3. Lighting (Optional but good practice)
scene.add(new THREE.AmbientLight(0xaaaaaa, 1)); // Soft ambient light
// 4. Create Particles
createGalaxyParticles();
createStarField();
// 5. Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove);
// Start the animation loop
animate();
}
/**
* Creates the main galaxy spiral particle system.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Generate particles in a helical/spiral pattern
for (let i = 0; i < particleCount; i++) {
// Parameter for spiral shape
const theta = Math.random() * Math.PI * 2; // Angle around Z axis
const zIndex = (Math.random() - 0.5) * 100; // Depth variation (-50 to 50)
// Spiral radius: r increases with z/depth, creating the spiral effect
let radius = Math.sqrt(Math.abs(zIndex)) * 0.5 + (Math.random() * 2);
// Cartesian coordinates for a helix-like structure
const x = Math.cos(theta) * radius;
const y = Math.sin(theta) * radius * 0.8; // Flattened slightly in Y
const z = zIndex + (Math.random() - 0.5) * 10;
positions.push(x, y, z);
// Assign random colors for a vibrant look
color.setHSL(Math.random(), 0.8, Math.random());
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup (PointMaterial is efficient for particles)
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors set in the geometry
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a dense, distant starfield background.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
// Use fewer particles for the stars to save performance
const starCount = 20000;
for (let i = 0; i < starCount; i++) {
// Distribute stars in a large cube volume
const x = (Math.random() - 0.5) * 1000;
const y = (Math.random() - 0.5) * 1000;
const z = (Math.random() - 0.5) * 1000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material setup for stars
const material = new THREE.PointsMaterial({
size: 1,
color: 0xffffff,
transparent: true,
opacity: 0.6
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
// =========================================
// INTERACTION HANDLERS
// =========================================
/**
* Updates mouse tracking variables.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX / window.innerWidth - 0.5) * 2; // Range: -1 to 1
mouseY = -(event.clientY / window.innerHeight - 0.5) * 2; // Range: -1 to 1 (flipped for camera tilt)
}
/**
* Handles resizing the canvas when the window size changes.
*/
function onWindowResize() {
camera.viewport.setSize(window.innerWidth, window.innerHeight);
renderer.setSize(window.innerWidth, window.innerHeight);
}
// =========================================
// ANIMATION LOOP AND LOGIC
// =========================================
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
// 1. Update Camera based on Mouse Input (Tilt)
camera.rotation.x += mouseY * 0.005;
camera.rotation.y += mouseX * 0.005;
// 2. Galaxy Rotation (Self-motion)
galaxyParticles.rotation.z += delta * 0.1; // Slow rotation around Z axis
galaxyParticles.rotation.x = Math.sin(clock.elapsedTime * 0.05) * 0.1;
galaxyParticles.rotation.y = Math.cos(clock.elapsedTime * 0.05) * 0.1;
// 3. Starfield Rotation (Subtle movement)
starFieldParticles.rotation.x += delta * 0.0001;
starFieldParticles.rotation.y += delta * 0.0002;
// Render the scene
renderer.render(scene, camera);
// Update FPS counter
updateFPS();
}
/**
* Updates and displays the Frames Per Second (FPS) count.
*/
function updateFPS() {
const currentTime = performance.now();
const elapsed = currentTime - lastTime;
frameCount++;
if (elapsed >= 1000) { // Update every second
const fps = Math.round((frameCount * 1000 / elapsed));
document.getElementById('fps-counter').innerText = `FPS: ${fps}`;
// Reset counters for the next second
frameCount = 0;
lastTime = currentTime;
}
}
// Initialize everything when the script loads
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an interactive 3D particle animation that simulates a galaxy with 5000 colorful particles, responds to mouse movement, and includes a starfield background with FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/stats.js@0.17.0/build/stats.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
max-width: 300px;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff758c);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 126, 179, 0.3);
}
#info p {
font-size: 1rem;
margin-bottom: 15px;
line-height: 1.5;
}
#info ul {
padding-left: 20px;
margin-bottom: 15px;
}
#info li {
margin-bottom: 8px;
font-size: 0.9rem;
}
#fps {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
font-family: monospace;
font-size: 1.2rem;
}
#controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
display: flex;
gap: 15px;
}
#controls button {
background: linear-gradient(to right, #ff7eb3, #ff758c);
border: none;
padding: 10px 20px;
border-radius: 30px;
color: white;
font-weight: bold;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 0 15px rgba(255, 117, 140, 0.5);
}
#controls button:hover {
transform: translateY(-3px);
box-shadow: 0 5px 20px rgba(255, 117, 140, 0.8);
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>This visualization shows a galaxy with <span class="highlight">5000 colorful particles</span> rotating in a spiral pattern.</p>
<ul>
<li>Move your mouse to tilt the galaxy</li>
<li>Particles follow a spiral galaxy structure</li>
<li>Starfield background for depth</li>
<li>FPS counter in the top-right corner</li>
</ul>
<p>Experience the beauty of cosmic motion!</p>
</div>
<div id="fps">FPS: 0</div>
<div id="controls">
<button id="resetBtn">Reset View</button>
<button id="speedUpBtn">Speed Up</button>
<button id="slowDownBtn">Slow Down</button>
</div>
</div>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let stats, clock;
let particleCount = 5000;
let rotationSpeed = 0.001;
let galaxyRadius = 500;
let galaxyHeight = 100;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 800;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Setup controls
document.getElementById('resetBtn').addEventListener('click', resetView);
document.getElementById('speedUpBtn').addEventListener('click', () => rotationSpeed *= 1.5);
document.getElementById('slowDownBtn').addEventListener('click', () => rotationSpeed *= 0.7);
// Initialize stats
stats = new Stats();
stats.showPanel(0); // 0: fps, 1: ms, 2: mb
document.getElementById('fps').appendChild(stats.dom);
// Initialize clock
clock = new THREE.Clock();
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy structure
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral pattern with some randomness
const radius = Math.random() * galaxyRadius;
const angle = Math.random() * Math.PI * 2;
const spiralAngle = angle + (radius / 100) * 5;
// Position particles in a spiral
const x = Math.cos(spiralAngle) * radius;
const y = Math.sin(spiralAngle) * radius;
const z = (Math.random() - 0.5) * galaxyHeight;
positions[i3] = x;
positions[i3 + 1] = y;
positions[i3 + 2] = z;
// Color particles with a gradient from blue to yellow to red
const color = new THREE.Color();
const hue = (radius / galaxyRadius) * 0.3 + Math.random() * 0.1;
color.setHSL(hue, 0.8, 0.5);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 3 + 1;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
gemma4:e4b
This is a complex request requiring advanced use of WebGL via Three.js. The solution provided below is self-contained in a single HTML file, ensuring maximum compatibility and ease of deployment.
It includes:
1. **A Galaxy Spiral:** 5000 points arranged in a spiral/disk shape.
2. **Mouse Interaction:** Tilts the entire scene based on cursor position.
3. **Starfield Background:** A secondary particle system for depth.
4. **FPS Counter:** Real-time performance monitoring.
### Interactive Particle Galaxy Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive 3D Particle Galaxy</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-family: 'Courier New', monospace;
padding: 10px;
background: rgba(0, 0, 0, 0.4);
border-radius: 5px;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: --</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Setup Variables ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
const NUM_GALACTIC = 5000;
const NUM_STARS = 15000;
// Mouse tracking variables for interaction
const mouse = new THREE.Vector2();
const clock = new THREE.Clock();
// FPS Counter Management
let frameCount = 0;
let lastTime = performance.now();
const fpsElement = document.getElementById('fpsCounter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// Scene Setup
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000011, 0.0005);
// Camera Setup (Perspective for depth)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Handle Window Resizing
window.addEventListener('resize', onWindowResize, false);
// Create the particle systems
createGalaxyParticles();
createStarfieldBackground();
// Event Listener for Mouse Interaction
document.addEventListener('mousemove', onDocumentMouseMove, false);
}
/**
* Creates the main galaxy spiral particle system.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const colors = [];
const positions = [];
// Parameters for a spiral shape (r = a * theta^b)
const MAX_RADIUS = 30;
const THETA_START = Math.PI * 0.5;
const THETA_END = Math.PI * 1.5;
for (let i = 0; i < NUM_GALACTIC; i++) {
// Generate angles for a spiral distribution
// Use i/NUM_GALACTIC to map index to angle range
let t = THETA_START + ((i / NUM_GALACTIC) * (THETA_END - THETA_START));
// Spiral calculation: Radius increases with angle
const r = Math.pow(t, 0.5) * (MAX_RADIUS / 2);
// Z coordinate is based on sine/cosine for a disk shape
let z = (Math.random() - 0.5) * 10; // Slight depth variation
// X and Y coordinates define the spiral projection
let x = r * Math.cos(t);
let y = r * Math.sin(t) * 0.8; // Flattened Y axis for better view
positions.push(x, y, z);
// Random vibrant color generation (Hues spread across the spectrum)
const hue = Math.random();
const color = new THREE.Color().setHSL(hue, 1.0, 0.5);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup (PointsMaterial is efficient for large point clouds)
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors defined in geometry
transparent: true,
opacity: 0.9
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a simple starfield background particle system.
*/
function createStarfieldBackground() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < NUM_STARS; i++) {
// Position stars far away to simulate a deep field
const x = Math.random() * 200 - 100;
const y = Math.random() * 200 - 100;
const z = Math.random() * 200 - 100;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a different material for stars (smaller, less intense)
const material = new THREE.PointsMaterial({
size: 0.1,
color: 0xaaaaee,
transparent: true,
opacity: 0.8
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
/**
* Handles the mouse movement event to calculate tilt offsets.
* @param {Event} event - The mouse move event.
*/
function onDocumentMouseMove(event) {
// Normalize mouse coordinates (-1 to +1)
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* Updates camera rotation based on mouse position.
*/
function updateCamera(deltaTime) {
// Smoothly rotate the camera and scene group
const rotationSpeed = 0.005;
camera.rotation.y += (mouse.x * rotationSpeed);
camera.rotation.x += (mouse.y * rotationSpeed);
// Optional: Add slight automatic yaw movement for a "floating" effect
scene.rotation.y += deltaTime * 0.05;
}
/**
* Main animation loop using requestAnimationFrame.
* @param {number} timestamp - High-resolution time stamp.
*/
function animate(timestamp) {
requestAnimationFrame(animate);
const delta = clock.getDelta(); // Time elapsed since last frame
// 1. Update Camera and Scene based on mouse input
updateCamera(delta);
// 2. Galaxy Rotation (The primary movement)
galaxyParticles.rotation.x += delta * 0.1;
galaxyParticles.rotation.y += delta * 0.15;
galaxyParticles.scale.setScalar(1 + Math.sin(timestamp / 3000) * 0.02); // Subtle breathing effect
// 3. Starfield Rotation (Slow, subtle movement to enhance depth)
starfieldParticles.rotation.y += delta * 0.005;
starfieldParticles.rotation.x += delta * 0.001;
// Render the scene
renderer.render(scene, camera);
// Update FPS Counter
updateFPS(timestamp);
}
/**
* Updates and displays the Frames Per Second counter.
* @param {number} timestamp - Current time stamp for calculation.
*/
function updateFPS(timestamp) {
frameCount++;
const elapsed = timestamp - lastTime;
if (elapsed >= 1000) { // Update every second
const fps = Math.round(frameCount * 1000 / elapsed);
fpsElement.innerHTML = `FPS: ${fps}`;
// Reset for next count
lastTime = timestamp;
frameCount = 0;
}
}
/**
* Handles viewport resizing.
*/
function onWindowResize() {
camera.viewport.setSize(window.innerWidth, window.innerHeight);
renderer.setSize(window.innerWidth, window.innerHeight);
}
// --- Initialization Call ---
init();
animate();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D galaxy animation with 5000 particles, mouse interaction, and a starfield background - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.9);
font-size: 28px;
font-weight: 300;
letter-spacing: 2px;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
}
#fps {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="title">3D GALAXY PARTICLE ANIMATION</div>
<div id="info">Interactive Galaxy Visualization | 5000 Particles | Mouse Control</div>
<div id="fps">FPS: 0</div>
<div id="instructions">Move mouse to tilt the galaxy • Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create the galaxy particle system
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy parameters
const radius = 150;
const spiralArms = 4;
const armAngle = (Math.PI * 2) / spiralArms;
const density = 0.05;
for (let i = 0; i < particleCount; i++) {
// Position particles in spiral pattern
const radiusFactor = Math.random() * 1.5;
const angle = Math.random() * Math.PI * 2;
const arm = Math.floor(Math.random() * spiralArms);
// Spiral formula with some randomness
const r = radius * Math.sqrt(Math.random()) * 0.8;
const a = arm * armAngle + (Math.random() - 0.5) * 0.3;
// Calculate position
const x = r * Math.cos(a) * (1 + Math.random() * 0.2);
const y = r * Math.sin(a) * (1 + Math.random() * 0.2);
const z = (Math.random() - 0.5) * 30;
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
// Color based on position
const color = new THREE.Color();
const hue = (Math.random() * 0.4) + 0.5; // Blue to purple range
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
// Random size
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starCount = 2000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(starCount * 3);
const colors = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const radius = 1000;
// Random position in sphere
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
const x = radius * Math.sin(phi) * Math.cos(theta);
const y = radius * Math.sin(phi) * Math.sin(theta);
const z = radius * Math.cos(phi);
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
// Star colors (mostly white with some blue/amber)
const color = new THREE.Color();
if (Math.random() > 0.8) {
color.setHSL(0.1, 0.5, 0.8); // Blue-white
} else if (Math.random() > 0.9) {
color.setHSL(0.12, 0.7, 0.7); // Amber
} else {
color.setRGB(1, 1, 1); // White
}
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.8
});
const starfield = new THREE.Points(geometry, material);
scene.add(starfield);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.inne
gemma4:e4b
This is a complex animation that requires robust handling of 3D geometry, event listeners, and performance tracking. The solution uses `BufferGeometry` for optimal rendering of thousands of points and implements an exponential function to simulate the spiral structure.
Here is the complete single-file HTML implementation:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Galaxy Particle Spiral Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fps-counter {
position: fixed;
top: 20px;
left: 20px;
color: white;
font-family: 'Arial', sans-serif;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 8px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Three.js CDN Link -->
<script src="https://cdn.jsdelivr.net/npm/three@r/build/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let particleSystem, starField;
const PARTICLES_COUNT = 5000;
let mouseX = 0, mouseY = 0;
// FPS tracking variables
let frameCount = 0;
let lastTime = performance.now();
let fpsDisplay;
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
scene.background = new THREE.Color(0x00000a); // Deep space blue/black
// 2. Camera Setup (Perspective)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 50;
// 3. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. Initialize Components
createParticleSystem();
createStarField();
setupEventListeners();
// Start the animation loop
animate();
}
/**
* Creates the main galaxy spiral particle system.
*/
function createParticleSystem() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < PARTICLES_COUNT; i++) {
// Calculate spiral coordinates using polar coordinates: r = a * theta, z = b * sin(theta)
const angle = Math.random() * Math.PI * 2; // Full circle rotation
// Spiral effect: Radius increases with the angle (r = constant * angle)
let radius = Math.pow(Math.random(), 1.5); // Gives a more structured, dense look
radius *= (angle / (Math.PI * 2)) * 4;
// Base coordinates for the spiral plane
const x = Math.cos(angle) * radius;
const y = Math.sin(angle) * radius * 0.5; // Flattened disk effect
const z = (Math.random() - 0.5) * 10; // Small depth variation
positions.push(x, y, z);
// Assign random colors for the "colorful" look
color.setHSL((i / PARTICLES_COUNT) + Math.random() * 0.1, 1.0, 0.7);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup for glowing particles
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors stored in the geometry
transparent: true,
opacity: 0.8
});
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
/**
* Creates a static starfield background.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const count = 50000; // More stars for density
for (let i = 0; i < count; i++) {
// Stars are placed far away in a cube
const x = (Math.random() - 0.5) * 1000;
const y = (Math.random() - 0.5) * 1000;
const z = (Math.random() - 0.5) * 1000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
size: 1,
color: 0xffffff,
transparent: true,
blending: THREE.AdditiveBlending // Gives a glowing effect
});
starField = new THREE.Points(geometry, material);
scene.add(starField);
}
/**
* Handles window resizing and updates the renderer size.
*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Handles mouse movement to provide interactive tilting effect.
*/
function onMouseMove(event) {
// Normalize coordinates (-1 to 1)
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* Sets up global event listeners.
*/
function setupEventListeners() {
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove);
}
// --- Animation Loop ---
function animate(time) {
requestAnimationFrame(() => animate(time));
const delta = (time - lastTime) / 1000; // Time in seconds since last frame
lastTime = time;
// 1. Update Camera based on Mouse Input (Tilt)
camera.rotation.y += (mouseX * 0.0005 - camera.rotation.y) * 0.05;
camera.rotation.x += (mouseY * 0.0005 - camera.rotation.x) * 0.05;
// 2. Update Particle System (Rotation and Spiral Flow)
const positions = particleSystem.geometry.attributes.position.array;
const timeFactor = delta * 0.1; // Controls speed of rotation/flow
for (let i = 0; i < PARTICLES_COUNT; i++) {
// The index offset for position attributes is 'i * 3'
const i3 = i * 3;
// Current coordinates
let x = positions[i3];
let y = positions[i3 + 1];
let z = positions[i3 + 2];
// Rotation around Y-axis (Galaxy spin)
const newX = Math.cos(timeFactor * 0.5) * x - Math.sin(timeFactor * 0.5) * y;
const newY = Math.sin(timeFactor * 0.5) * x + Math.cos(timeFactor * 0.5) * y;
// Spiral/Flow effect: Adjust Z position based on time and current X/Y
// This makes the particles appear to flow or orbit slightly
const newZ = z + (Math.sin((x / 20) + (y / 20) + timeFactor * 5)) * 0.01;
positions[i3] = newX;
positions[i3 + 1] = newY;
positions[i3 + 2] = newZ;
}
// Flag Three.js that the geometry data has changed
particleSystem.geometry.attributes.position.needsUpdate = true;
// 3. Update Star Field (Subtle movement for depth)
const starPositions = starField.geometry.attributes.position.array;
for (let i = 0; i < starPositions.length; i += 3) {
starPositions[i] += Math.sin(time * 0.0001 + i/1000) * 0.001;
starPositions[i+2] -= Math.cos(time * 0.0001 + i/500) * 0.001;
}
starField.geometry.attributes.position.needsUpdate = true;
// 4. Render and FPS Update
renderer.render(scene, camera);
updateFPS(delta);
}
/**
* Calculates and displays the Frames Per Second (FPS) counter.
* @param {number} delta - Time elapsed since last frame in seconds.
*/
function updateFPS(deltaTime) {
frameCount++;
const timeElapsed = performance.now() - lastTime;
if (timeElapsed >= 1000) { // Update display every second
const fps = Math.round(frameCount / (timeElapsed / 1000));
document.getElementById('fps-counter').textContent = `FPS: ${fps}`;
frameCount = 0;
}
}
// --- Execution Start ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy animation with 5000 particles that respond to mouse movement and include a starfield background with an FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
z-index: 10;
max-width: 300px;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff758c);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 126, 179, 0.3);
}
#info p {
margin-bottom: 10px;
font-size: 0.9rem;
line-height: 1.5;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
font-family: monospace;
z-index: 10;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
text-align: center;
backdrop-filter: blur(5px);
font-size: 0.9rem;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive Galaxy Animation</h1>
<p>This 3D particle system simulates a galaxy with <span class="highlight">5000 colorful particles</span> rotating in a spiral pattern.</p>
<p>Move your mouse to tilt the galaxy and explore its structure. The background features a starfield for depth.</p>
<p>Notice how particles form spiral arms that rotate around the center of the galaxy.</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Scroll to zoom in/out</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0, lastTime: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
controls.zoomSpeed = 1.2;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create the galaxy particle system
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position particles in a spiral pattern
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 4;
const height = (Math.random() - 0.5) * 100;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Create color gradient (blue to yellow to red)
const color = new THREE.Color();
const hue = (Math.random() * 0.2) + 0.5; // Blue to yellow
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Update particle system rotation
if (particleSystem) {
particleSystem.rotation.y += 0.001;
// Mouse tilt effect
camera.position.x += (mouseX * 5 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 5 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
// Update FPS counter
updateFPS(delta);
}
// Update FPS counter
function updateFPS(delta) {
const now = performance.now();
if (now >= stats.lastTime + 1000) {
stats.fps = Math.round(1000 / delta);
document.getElementById('fps-counter').textContent =
gemma4:e4b
This is a complete, self-contained HTML file that implements the requested interactive 3D particle animation using Three.js.
### ✨ Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Spiral</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000010; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
right: 20px;
color: rgba(255, 255, 255, 0.6);
font-family: 'Arial', sans-serif;
font-size: 18px;
padding: 10px;
background: rgba(0, 0, 0, 0.4);
border-radius: 5px;
user-select: none;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 60</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
let clock = new THREE.Clock();
let mouseX = 0;
let mouseY = 0;
const CONTAINER_ID = 'fps-counter';
// --- Initialization Function ---
function init() {
// 1. Setup Scene, Camera, Renderer
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set initial camera position
camera.position.z = 50;
// 2. Create the Galaxy Spiral Particles (The main attraction)
createGalaxySpiral();
// 3. Create the Starfield Background
createStarfield();
// 4. Event Listeners
window.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Start the animation loop
animate();
}
/**
* Generates particles forming a spiral structure (galaxy-like).
*/
function createGalaxySpiral() {
const count = 5000;
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Galaxy parameters
const maxRadius = 150;
const spiralFactor = 0.02; // Controls how tightly wound the spiral is
for (let i = 0; i < count; i++) {
// Map index 'i' to an angle theta for spiraling effect
const theta = (i / count) * Math.PI * 8;
// Calculate radius using a function that increases with angle (spiral shape)
// r = A * theta^B -> We use a modified version
let radius = maxRadius * (1 - Math.cos(theta));
if (radius < 5) radius = 5; // Minimum size
// Calculate Z depth and X position
const z = Math.sin(theta) * maxRadius / 2;
const x = Math.cos(theta) * radius;
const y = (Math.random() - 0.5) * 10; // Small vertical variation
positions.push(x, y + z, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Create randomized colors for the particles
for (let i = 0; i < count; i++) {
const color = new THREE.Color();
color.setHSL(i / count * 0.6 + 0.5, 1, 0.7); // Hue changes slowly
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Use PointsMaterial for rendering efficiency
const material = new THREE.PointsMaterial({
size: 1.5, // Size of each particle
vertexColors: true, // Use the per-particle color attribute
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a dense but static background starfield.
*/
function createStarfield() {
const count = 10000;
const geometry = new THREE.SphereGeometry(500, 32, 32); // Use Sphere for volume
const positions = [];
// Fill the sphere with random points (stars)
for (let i = 0; i < count; i++) {
// Generate coordinates within a large bounding box
positions.push(
Math.random() * 2000 - 1000, // x
Math.random() * 2000 - 1000, // y
Math.random() * 2000 - 1000 // z
);
}
const geometryStars = new THREE.BufferGeometry();
geometryStars.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const materialStar = new THREE.PointsMaterial({
size: 1.5,
color: 0xaaaaff, // Soft blue/white color
transparent: true,
opacity: 0.6
});
starfieldParticles = new THREE.Points(geometryStars, materialStar);
scene.add(starfieldParticles);
}
// --- Event Handlers ---
/**
* Updates mouse coordinates for camera tilt effect.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - window.innerWidth / 2) * 0.5;
mouseY = (event.clientY - window.innerHeight / 2) * 0.5;
}
/**
* Handles screen resizing to maintain aspect ratio.
*/
function onWindowResize() {
camera.viewport.needsUpdate = true;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// --- Animation Loop and Logic ---
let lastTime = 0;
const fpsElement = document.getElementById(CONTAINER_ID);
function animate(time) {
requestAnimationFrame(animate);
const delta = clock.getDelta();
// --- Rotation and Movement ---
// 1. Galaxy Rotation (slow spin around Y-axis)
galaxyParticles.rotation.y += 0.001;
galaxyParticles.rotation.x = Math.sin(time * 0.0001) * 0.1;
// 2. Starfield subtle rotation (simulating cosmic drift)
starfieldParticles.rotation.y += 0.0001;
// 3. Camera Tilt Effect (Reacts to mouse movement)
// We use the current time for smooth oscillation alongside the mouse input
const targetRotationX = mouseY * 0.0001 + Math.sin(time * 0.0005) * 0.1;
const targetRotationY = mouseX * 0.0001 + Math.cos(time * 0.0005) * 0.1;
// Smoothly interpolate the camera rotation towards the desired tilt
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.03;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.03;
// --- Rendering ---
renderer.render(scene, camera);
// --- FPS Calculation ---
const currentTime = performance.now();
let elapsedSeconds = (currentTime - lastTime) / 1000;
let fps = elapsedSeconds > 0 ? Math.round(1 / elapsedSeconds) : 60;
fpsElement.textContent = `FPS: ${fps}`;
lastTime = currentTime;
}
// --- Execution Start ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy simulation with 5000 particles that respond to mouse movement and include a starfield background with FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Simulation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
margin: 8px 0;
font-size: 0.9rem;
opacity: 0.8;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
font-family: monospace;
}
#controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
gap: 15px;
}
#controls button {
background: linear-gradient(to right, #ff7eb3, #ff70a6);
border: none;
padding: 8px 15px;
border-radius: 20px;
color: white;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
}
#controls button:hover {
transform: scale(1.05);
box-shadow: 0 0 15px rgba(255, 110, 179, 0.5);
}
.particle-count {
position: absolute;
bottom: 80px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
font-size: 0.9rem;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>3D Galaxy Simulation</h1>
<p>Interactive particle galaxy with mouse tilt effect</p>
<p>5,000 particles rotating in spiral arms</p>
</div>
<div id="fps-counter">FPS: 60</div>
<div class="particle-count">Particle Count: 5,000</div>
<div id="controls">
<button id="speedUp">Speed Up</button>
<button id="slowDown">Slow Down</button>
<button id="reset">Reset</button>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let rotationSpeed = 0.001;
let clock = new THREE.Clock();
let stats;
let particlesArray = [];
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create particles
createParticles();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Setup controls
setupControls();
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createParticles() {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy structure
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position particles in spiral arms
const radius = Math.random() * 300;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 50;
// Spiral arm structure
const spiralAngle = angle + (radius / 100) * 3;
const x = radius * Math.cos(spiralAngle);
const y = radius * Math.sin(spiralAngle);
const z = height;
positions[i3] = x;
positions[i3 + 1] = y;
positions[i3 + 2] = z;
// Random color with some blue/red tones for galaxy effect
const color = new THREE.Color();
const hue = Math.random() * 0.4 + 0.5; // Blue to red range
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.3 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random particle size
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Setup controls
function setupControls() {
document.getElementById('speedUp').addEventListener('click', () => {
rotationSpeed = Math.min(rotationSpeed + 0.0005, 0.01);
});
document.getElementById('slowDown').addEventListener('click', () => {
rotationSpeed = Math.max(rotationSpeed - 0.0005, 0.0001);
});
gemma4:e4b
This is a comprehensive solution that combines modern web graphics techniques (Three.js) with complex geometry generation and real-time interaction handling, all within a single HTML file.
### 🌌 Cosmic Spiral Particle Animator
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Spiral</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 20px;
left: 20px;
padding: 8px 15px;
background: rgba(0, 0, 0, 0.6);
color: #ffffff;
font-family: 'Arial', sans-serif;
border-radius: 8px;
user-select: none; /* Prevent selection */
z-index: 100;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 60</div>
<!-- Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
let mouseX = 0, mouseY = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
// FPS Tracking Variables
let frameCount = 0;
let lastTime = performance.now();
const fpsDisplay = document.getElementById('fpsCounter');
/**
* Initializes the Three.js environment (Scene, Camera, Renderer).
*/
function init() {
// Scene setup
scene = new THREE.Scene();
// Camera setup: Perspective camera suited for cosmic views
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.set(0, 0, 500);
camera.lookAt(0, 0, 0);
// Renderer setup: Using high precision for visual quality
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// --- Event Listeners ---
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove);
// --- Create Components ---
createGalaxyParticles(5000);
createStarField(20000);
// Start the animation loop
animate();
}
/**
* Generates the main spiral particle system (The Galaxy).
* Uses mathematical spirals for realistic geometry.
* @param {number} count - Number of particles to generate.
*/
function createGalaxyParticles(count) {
const points = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Parameters controlling the spiral shape and size
const maxTheta = Math.PI * 8; // Total angular spread (4 full rotations)
const radiusScaleFactor = 150;
const zDepthScaleFactor = -300;
for (let i = 0; i < count; i++) {
// Calculate angle (theta) and distance along the spiral path
const theta = (i / count) * maxTheta;
// Spiral geometry: r = a * theta (Archimedean spiral approximation)
// This gives particles that spread out as they rotate.
const radius = Math.pow(theta / maxTheta, 0.5) * radiusScaleFactor;
// X and Y coordinates based on polar to Cartesian conversion
const x = Math.cos(theta) * radius;
const y = Math.sin(theta) * radius * 0.6; // Slightly compress the vertical spread
// Z coordinate (depth/distance along the spiral axis, creating a disc effect)
const z = theta * (zDepthScaleFactor / maxTheta);
positions.push(x, y, z);
// Assign random colors for a colorful look
const color = new THREE.Color();
color.setHSL(i / count + 0.5, 1.0, Math.random() * 0.5 + 0.3); // Hue shift
colors.push(color.r, color.g, color.b);
}
// Set up the BufferGeometry with positions and attributes for colors
points.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
points.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup: Use PointsMaterial to render particles efficiently
const material = new THREE.PointsMaterial({
size: 1 + Math.random() * 1.5, // Slight variation in size
vertexColors: true, // Crucial: use the assigned colors
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(points, material);
scene.add(galaxyParticles);
}
/**
* Generates a dense, random starfield background.
* @param {number} count - Number of stars to generate.
*/
function createStarField(count) {
const positions = [];
for (let i = 0; i < count; i++) {
// Generate points far away from the origin, simulating a vast skybox/background
const x = (Math.random() - 0.5) * 4000;
const y = (Math.random() - 0.5) * 4000;
const z = (Math.random() - 0.5) * 4000;
positions.push(x, y, z);
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a simple white material for distant stars
const material = new THREE.PointsMaterial({
size: 1,
color: 0xAAAAFF, // Light blue/white glow
transparent: true,
opacity: 0.7
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
/**
* Handles window resizing to keep the view responsive.
*/
function onWindowResize() {
camera.viewport = { x: 0, y: 0, width: 1, height: 1 };
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Captures mouse movement data for interactive camera tilt.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100; // Scale down the input
mouseY = (event.clientY - windowHalfY) / 100;
}
/**
* The main animation loop. Updates object positions and renders the scene.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() * 0.001;
// --- 1. Galaxy Animation (Rotation) ---
if (galaxyParticles) {
// Rotate around Y-axis for a classic galactic spin
galaxyParticles.rotation.y += 0.0005;
// Subtle slow rotation on X and Z to give depth
galaxyParticles.rotation.x = Math.sin(time * 0.1) * 0.1;
}
// --- 2. Starfield Animation (Subtle movement/parallax effect) ---
if (starFieldParticles) {
// Make the stars slowly drift over time for a sense of depth
starFieldParticles.rotation.y += 0.0001;
starFieldParticles.position.z = Math.sin(time * 0.5) * 20;
}
// --- 3. Camera Response (Mouse Tilt) ---
// Adjust camera target/position based on mouse input for a 'looking at' effect
camera.lookAt(0, 0, 0);
const targetX = Math.sin(time * 0.1) * 5 + mouseX * 0.5;
const targetY = -Math.cos(time * 0.1) * 5 + mouseY * 0.5;
camera.position.x += (targetX - camera.position.x) * 0.05;
camera.position.y += (targetY - camera.position.y) * 0.05;
// --- 4. Render and Update FPS ---
renderer.render(scene, camera);
updateFPS();
}
/**
* Calculates and displays the Frames Per Second counter.
*/
function updateFPS() {
const currentTime = performance.now();
const delta = currentTime - lastTime;
// Calculate FPS: 1000ms / time elapsed since last frame
const fps = Math.round(1000 / (delta / frameCount));
fpsDisplay.textContent = `FPS: ${Math.max(20, fps)}`; // Minimum display of 20 to avoid flicker
// Reset counters for the next second
frameCount++;
if (currentTime - lastTime >= 1000) {
lastTime = currentTime;
frameCount = 0;
}
}
// --- Initialization Call ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive 3D particle galaxy animation with mouse interaction, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
cursor: pointer;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.8);
font-size: 24px;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
letter-spacing: 2px;
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="title">3D GALAXY PARTICLE ANIMATION</div>
<div id="info">Interactive Particle Galaxy | 5000 Particles | Mouse Tilt Control</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move mouse to tilt galaxy | Click to change color palette</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats;
let colorPaletteIndex = 0;
const colorPalettes = [
[0.1, 0.2, 0.8], // Blue
[0.8, 0.1, 0.3], // Red
[0.1, 0.8, 0.4], // Green
[0.9, 0.6, 0.1], // Orange
[0.7, 0.2, 0.8] // Purple
];
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setAnimationLoop(animate);
document.getElementById('container').appendChild(renderer.domElement);
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.addEventListener('click', changeColorPalette);
// Initialize FPS counter
const fpsCounter = document.getElementById('fps-counter');
let frameCount = 0;
let lastTime = performance.now();
function updateFPS() {
frameCount++;
const now = performance.now();
if (now >= lastTime + 1000) {
fpsCounter.textContent = `FPS: ${Math.round(frameCount * 1000 / (now - lastTime))}`;
frameCount = 0;
lastTime = now;
}
requestAnimationFrame(updateFPS);
}
updateFPS();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy particles in spiral formation
for (let i = 0; i < particleCount; i++) {
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 40;
// Position
positions[i * 3] = Math.cos(angle) * radius;
positions[i * 3 + 1] = height;
positions[i * 3 + 2] = Math.sin(angle) * radius;
// Color (based on position for spiral effect)
const color = new THREE.Color();
const palette = colorPalettes[colorPaletteIndex];
color.setRGB(palette[0], palette[1], palette[2]);
// Add some variation to colors
color.r += (Math.random() - 0.5) * 0.5;
color.g += (Math.random() - 0.5) * 0.5;
color.b += (Math.random() - 0.5) * 0.5;
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
// Size
sizes[i] = Math.random() * 3 + 1;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Change color palette
function changeColorPalette() {
colorPaletteIndex = (colorPaletteIndex + 1) % colorPalettes.length;
// Update existing particles
const positions = particles.geometry.attributes.position.array;
const colors = particles.geometry.attributes.color.array;
for (let i = 0; i < particleCount; i++) {
const palette = colorPalettes[colorPaletteIndex];
const color = new THREE.Color();
color.setRGB(palette[0], palette[1], palette[2]);
// Add some variation to colors
color.r += (Math.random() - 0.5) * 0.5;
color.g += (Math.random() - 0.5) * 0.5;
color.b += (Math.random() - 0.5) * 0.5;
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
}
gemma4:e4b
This is a complex, high-performance animation that requires careful optimization using Three.js's geometry features. We will use `BufferGeometry` and `Points` to render the 5000 particles efficiently.
Here is the complete single HTML file solution:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000; }
canvas { display: block; }
#fps-counter {
position: fixed;
top: 10px;
left: 10px;
color: rgba(255, 255, 255, 0.7);
font-family: monospace;
padding: 8px 15px;
background: rgba(0, 0, 0, 0.5);
border-radius: 5px;
pointer-events: none; /* Ensures it doesn't block mouse events */
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 60</div>
<!-- Include Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starField;
let mouseX = 0;
let mouseY = 0;
// FPS tracking variables
let frameCount = 0;
let lastTime = performance.now();
const fpsDiv = document.getElementById('fps-counter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// Scene setup
scene = new THREE.Scene();
scene.background = new THREE.Color(0x00000a);
// Camera setup (Perspective)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// Renderer setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
// Create the objects
createGalaxyParticles();
createStarField();
// Start the animation loop
animate();
}
/**
* Creates the main particle system in a spiral galaxy formation (5000 particles).
*/
function createGalaxyParticles() {
const count = 5000;
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Particle attributes setup
for (let i = 0; i < count; i++) {
// Parameterization for a spiral shape: r(t) * cos(k*t), r(t) * sin(k*t)
// t is the angle/position parameter
const t = i / count * Math.PI * 6; // Angle sweep (3 full rotations)
// Spiral radius and depth (r increases with angle)
const r = Math.random() * 10 + (t / (Math.PI * 2)) * 5;
// Calculate positions in X, Y, Z based on spiral projection
positions.push(r * Math.cos(t)); // x
positions.push(r * Math.sin(t) * 0.8); // y (Slightly compressed vertically)
positions.push(r * Math.sin(t) * 0.7); // z
// Assign random colors for visual depth
const color = new THREE.Color();
color.setHSL(i / count, 1.0, 0.5); // Hue changes smoothly across the spiral
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material using vertex colors for individual particle coloring
const material = new THREE.PointsMaterial({
size: 0.8, // Size of the particles
vertexColors: true, // Use the color attribute set in geometry
transparent: true,
opacity: 0.9
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a static starfield background using a simple Points object.
*/
function createStarField() {
const count = 15000;
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < count; i++) {
// Place stars randomly far away from the origin
positions.push(Math.random() * 400 - 200); // x
positions.push(Math.random() * 400 - 200); // y
positions.push(Math.random() * 400 - 200); // z
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
size: 1.5,
color: 0xaaaaee,
transparent: true,
opacity: 0.8
});
starField = new THREE.Points(geometry, material);
scene.add(starField);
}
/**
* Handles window resizing to keep the canvas fullscreen.
*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates mouse coordinates for camera/object interaction.
*/
function onDocumentMouseMove(event) {
// Normalize coordinates (-1 to +1)
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 - 1;
}
/**
* The main animation loop.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() / 1000; // Time in seconds
// --- Animation Updates ---
// 1. Galaxy Rotation (Spiral movement)
galaxyParticles.rotation.y += 0.0015; // Slow continuous rotation
galaxyParticles.rotation.x = Math.sin(time * 0.2) * 0.1; // Gentle wobble on X axis
// 2. Starfield Movement (Subtle shift for parallax effect)
starField.position.y += 0.0005;
if (starField.position.y > 50) starField.position.y = -50;
// 3. Mouse Interaction (Camera Tilt/LookAt)
// We smoothly interpolate the camera rotation based on mouse input
camera.rotation.x += (mouseY * 0.1 - camera.rotation.x) * 0.05;
camera.rotation.y += (mouseX * 0.1 - camera.rotation.y) * 0.05;
// --- Rendering and FPS ---
renderer.render(scene, camera);
// Update FPS counter
updateFPS();
}
/**
* Calculates and displays the Frames Per Second (FPS).
*/
function updateFPS() {
const currentTime = performance.now();
const delta = currentTime - lastTime;
frameCount++;
if (delta >= 1000) { // Update every second
const fps = Math.round(1000 / ((currentTime - lastTime) / frameCount));
fpsDiv.textContent = `FPS: ${Math.max(1, fps)}`;
// Reset counters
frameCount = 0;
lastTime = currentTime;
}
}
// --- Initialization Call ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an interactive 3D particle galaxy animation with mouse tilt response, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.8);
font-size: 24px;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
letter-spacing: 2px;
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
z-index: 100;
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="title">3D GALAXY PARTICLE ANIMATION</div>
<div id="info">Interactive Galaxy Simulation | 5,000 Particles</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats;
let fpsElement;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 50, 150);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 50;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Initialize FPS counter
fpsElement = document.getElementById('fps-counter');
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.2,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy with spiral arms
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position particles in spiral pattern
const radius = Math.sqrt(Math.random()) * 50;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color based on position for spiral effect
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) * 0.4 + 0.5; // Blue to red spectrum
const saturation = 0.7 + Math.random() * 0.3;
const lightness = 0.4 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Size variation
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate galaxy
if (particleSystem) {
particleSystem.rotation.y += 0.001;
// Tilt based on mouse position
camera.position.x += (mouseX * 5 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 5 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
// Update FPS counter
const fps = Math.round(1 / delta);
fpsElement.textContent = `FPS: ${fps}`;
}
// Start the animation
init();
animate();
</script>
</body>
</html>
```
## Features of this Interactive Galaxy Animation:
1. **Realistic Galaxy Simulation**:
- 5,000 colorful particles arranged in a spiral galaxy pattern
- Particles have varying sizes and colors for visual depth
- Smooth rotation animation
2. **Interactive Elements**:
- Mouse movement tilts the galaxy in real-time
- Orbit controls allow zooming and panning
- Responsive design that adapts to window size
3. **Visual Enhancements**:
- Starfield background with 10,000 stars
- Smooth particle animation with depth effects
- Fog effect for atmospheric perspective
- Colorful spiral arms with gradient hues
4. **Performance Monitoring**:
- Real-time FPS counter in the bottom-right corner
- Optimized rendering for smooth performance
5. **User Interface**:
- Clean, space-themed design
- Informati
gemma4:e4b
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: #fff;
font-family: monospace;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<!-- FPS Counter Display -->
<div id="fps-counter">FPS: 60</div>
<!-- Three.js Library CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// ========================================================
// GLOBAL SETUP VARIABLES
// ========================================================
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
let mouseX = 0;
let mouseY = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
// FPS Tracking Variables
let frameCount = 0;
let lastTime = performance.now();
const fpsDisplay = document.getElementById('fps-counter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// Scene setup
scene = new THREE.Scene();
// Camera setup (Perspective is best for depth)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = -50;
// Renderer setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove);
// Create the particle systems
createGalaxyParticles();
createStarfieldParticles();
// Start the animation loop
animate();
}
/**
* Creates the main spiral galaxy particles (5000 total).
*/
function createGalaxyParticles() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Create particles in a spiral pattern (simulating a galaxy disk)
for (let i = 0; i < particleCount; i++) {
// Use polar coordinates for the spiral: r = A * theta, z = constant
// This creates a visible spiral shape.
const theta = Math.random() * Math.PI * 2; // Angle in radians
const radius = (Math.random() / particleCount) * 150 + 5; // Radial distance
const zPos = ((i / particleCount) - 0.5) * 80; // Depth along Z axis
// Calculate X, Y positions for the spiral shape
const x = Math.cos(theta) * radius * (1 + (zPos / 50));
const y = Math.sin(theta) * radius * (1 + (zPos / 50)) * (Math.random() * 0.2 + 0.8); // Slight vertical variation
positions.push(x, y, zPos);
// Assign random vibrant colors
color.setHSL(Math.random(), 0.8, Math.random() * 0.6 + 0.3);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup (using PointsMaterial for efficiency)
const material = new THREE.PointsMaterial({
size: 1.5, // Size of the particles
vertexColors: true, // Use vertex colors defined in geometry
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a dense starfield background particle system.
*/
function createStarfieldParticles() {
const starCount = 30000;
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < starCount; i++) {
// Distribute stars across a large cube volume
const x = (Math.random() - 0.5) * 400;
const y = (Math.random() - 0.5) * 400;
const z = (Math.random() - 0.5) * 400;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material setup for stars
const material = new THREE.PointsMaterial({
size: 1.5,
color: 0xffffff,
transparent: true,
opacity: 0.8
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
/**
* Handles window resizing to keep the canvas size correct.
*/
function onWindowResize() {
camera.viewport.set(0, 0, 1, 1); // Reset viewport if needed
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates mouse coordinates used for camera tilt effect.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 200; // Normalize and scale
mouseY = (event.clientY - windowHalfY) / 200;
}
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() * 0.001;
// 1. Galaxy Rotation (Self-rotation)
galaxyParticles.rotation.x += 0.00005;
galaxyParticles.rotation.y += 0.001;
// 2. Starfield Drift/Rotation (Subtle movement)
starfieldParticles.rotation.y = time * 0.05;
starfieldParticles.position.z = Math.sin(time * 0.1) * 50;
// 3. Camera Tilt/LookAt based on Mouse Movement
const targetRotationX = mouseY * 0.0002;
const targetRotationY = mouseX * 0.0002;
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.05;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.05;
// 4. Render the scene
renderer.render(scene, camera);
// FPS Counter Update
updateFPS();
}
/**
* Calculates and displays the Frames Per Second counter.
*/
function updateFPS() {
const currentTime = performance.now();
const elapsed = currentTime - lastTime;
if (elapsed >= 500) { // Update FPS every half second for stability
const fps = Math.round(1000 / ((currentTime - lastTime) / frameCount));
fpsDisplay.innerText = `FPS: ${fps}`;
frameCount = 0;
lastTime = currentTime;
}
frameCount++;
}
// Initialize everything when the script loads
init();
</script>
</body>
</html>
```
qwen3:32b-q4_K_M
Here's a complete, interactive 3D galaxy particle animation using **Three.js** and **Stats.js** for an FPS counter, all in **one HTML file**. The animation features:
- **5000 colorful particles** forming a spiral galaxy.
- **Mouse tilt interaction** for dynamic camera control.
- **Starfield background** for depth.
- **FPS counter** in the corner.
---
### ✅ Save the following code as `index.html` and open it in a browser.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Galaxy Particle Animation</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #000;
}
canvas {
display: block;
}
#stats {
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
</style>
</head>
<body>
<div id="stats"></div>
<script src="https://cdn.jsdelivr.net/npm/three@0.152.2/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.152.2/examples/js/libs/stats.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// FPS counter
const stats = new Stats();
stats.dom.id = "stats";
document.body.appendChild(stats.dom);
// Camera position and mouse tracking
camera.position.z = 30;
let mouseX = 0, mouseY = 0;
let targetX = 0, targetY = 0;
document.addEventListener('mousemove', (e) => {
mouseX = (e.clientX - window.innerWidth / 2) / window.innerWidth * 2;
mouseY = (e.clientY - window.innerHeight / 2) / window.innerHeight * 2;
});
// Galaxy particle system
const galaxyPoints = createGalaxy(5000, 0.02, 0.005, 10);
scene.add(galaxyPoints);
// Starfield background
const starfield = createStarfield(2000);
scene.add(starfield);
// Animation loop
function animate() {
requestAnimationFrame(animate);
stats.begin();
// Smooth camera tilt
targetX = mouseX * 0.1;
targetY = -mouseY * 0.1;
camera.rotation.x += (targetY - camera.rotation.x) * 0.05;
camera.rotation.y += (targetX - camera.rotation.y) * 0.05;
// Rotate galaxy
galaxyPoints.rotation.z += 0.001;
renderer.render(scene, camera);
stats.end();
}
animate();
// Resize handler
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// Helper functions
function createGalaxy(count, radiusFactor, noiseFactor, size) {
const positions = new Float32Array(count * 3);
const colors = new Float32Array(count * 3);
const color = new THREE.Color();
for (let i = 0; i < count; i++) {
const i3 = i * 3;
const radius = radiusFactor * Math.sqrt(i);
const angle = i * 0.1 + Math.random() * 0.5;
const z = Math.random() * 20 - 10;
positions[i3] = Math.cos(angle) * radius + (Math.random() - 0.5) * noiseFactor;
positions[i3 + 1] = Math.sin(angle) * radius + (Math.random() - 0.5) * noiseFactor;
positions[i3 + 2] = z;
const hue = (angle + i * 0.001) / (2 * Math.PI);
color.setHSL(hue, 1, 0.5);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: size,
vertexColors: true,
transparent: true,
blending: THREE.AdditiveBlending,
depthWrite: false
});
return new THREE.Points(geometry, material);
}
function createStarfield(count) {
const positions = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
const i3 = i * 3;
positions[i3] = (Math.random() - 0.5) * 200;
positions[i3 + 1] =
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D galaxy animation with 5000 colorful particles, responsive mouse tilt, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
cursor: pointer;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#fps {
position: absolute;
top: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: rgba(255, 255, 255, 0.8);
font-size: 36px;
text-align: center;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
pointer-events: none;
opacity: 0.8;
}
#title span {
display: block;
font-size: 18px;
margin-top: 10px;
font-weight: normal;
letter-spacing: 2px;
}
.instructions {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
text-align: center;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 20px;
border-radius: 20px;
backdrop-filter: blur(5px);
}
</style>
</head>
<body>
<div id="container">
<div id="info">Interactive 3D Galaxy</div>
<div id="fps">FPS: 0</div>
<div id="title">GALAXY PARTICLE SYSTEM<span>Move your mouse to tilt the galaxy</span></div>
<div class="instructions">Move mouse to tilt | Click to change particle color</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats = { fps: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 100;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.addEventListener('click', changeParticleColor);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const material = new THREE.PointsMaterial({
size: 1.5,
sizeAttenuation: true,
vertexColors: true,
transparent: true,
opacity: 0.9
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy structure
for (let i = 0; i < particleCount; i++) {
const radius = Math.sqrt(Math.random()) * 100;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
// Spiral arms
const armAngle = angle + (Math.sin(radius * 0.1) * 0.5);
positions[i * 3] = Math.cos(armAngle) * radius;
positions[i * 3 + 1] = height;
positions[i * 3 + 2] = Math.sin(armAngle) * radius;
// Color variation
const color = new THREE.Color();
const hue = (radius / 100) * 0.4 + 0.5; // Shift towards blue-green
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.3 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
// Size variation
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.0005;
mouseY = (event.clientY - windowHalfY) * 0.0005;
}
// Window resize handler
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Change particle color on click
function changeParticleColor() {
const color = new THREE.Color(Math.random(), Math.random(), Math.random());
particles.material.color = color;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Rotate particles
if (particles) {
particles.rotation.x += 0.0005;
particles.rotation.y += 0.001;
// Mouse tilt effect
camera.position.x += (mouseX * 5 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 5 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update FPS counter
stats.fps = Math.round(1 / delta);
document.getElementById('fps').textContent = `FPS: ${stats.fps}`;
renderer.render(scene, camera);
}
// Initialize the scene when the page loads
window.onload = init;
</script>
</body>
</html>
```
## Features of this Interactive 3D Galaxy:
1. **5000 Colorful Particles**: Created in a realistic galaxy spiral pattern with varying colors and sizes
2. **Mouse Interaction**:
- Move mouse to tilt the galaxy in 3D space
- Click anywhere to change particle color
3. **Starfield Background**: Thousands of stars create a c
gemma4:e4b
This is a complex task requiring advanced Three.js knowledge for performance and visual fidelity. Below is the complete single HTML file containing all CSS, JavaScript, and the necessary library imports to run the interactive 3D particle animation.
The script implements:
1. **Galaxy Spiral:** Particles are mathematically placed in a spiral pattern.
2. **Mouse Interaction (Tilt):** The camera smoothly rotates based on cursor movement (pitch/yaw).
3. **Starfield Background:** A secondary field of random points adds depth.
4. **Performance Monitoring:** An accurate FPS counter is displayed using the `requestAnimationFrame` cycle timing.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.6);
color: #ffffff;
padding: 8px 15px;
border-radius: 5px;
font-family: 'Courier New', monospace;
z-index: 100;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<!-- Three.js Library CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
const PARTICLES_COUNT = 5000;
let particlesGeometry, particlesMaterial, particleSystem;
let starfieldPoints;
// Interaction variables
const mouseSensitivity = 0.001; // Adjust sensitivity here
let targetRotationX = 0;
let targetRotationY = 0;
// FPS tracking variables
let frameCount = 0;
let lastTime = performance.now();
let fpsIntervalTimer = null;
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// 1. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 2. Scene Setup
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000011, 0.005); // Adds depth effect
// 3. Camera Setup (Perspective camera for depth perception)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// --- Particle System Generation (The Galaxy Spiral) ---
createParticles();
// --- Starfield Background ---
createStarfield(300); // Create stars up to radius 300
// --- Event Listeners ---
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('resize', onWindowResize);
// Start the animation loop
animate();
}
/**
* Creates and positions the 5000 particles in a spiral pattern.
*/
function createParticles() {
particlesGeometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Spiral parameters (controls how tightly wound the galaxy is)
const spiralFactor = 0.1; // Controls radius growth vs angle
const maxAngle = Math.PI * 8; // Total sweep angle (360 degrees * 4)
const maxRadius = 200;
const colorPalette = [
new THREE.Color(0x99ccff), new THREE.Color(0xcc99ff),
new THREE.Color(0xff99cc), new THREE.Color(0xffff66)
];
for (let i = 0; i < PARTICLES_COUNT; i++) {
// Distribute particles evenly along the angle
const theta = (i / PARTICLES_COUNT) * maxAngle; // Angle in radians
// Calculate radius based on spiral factor and angle
const r = Math.min(maxRadius, spiralFactor * theta);
// X: r * cos(theta)
// Y: random vertical scatter for depth (slight Z axis deviation)
// Z: r * sin(theta)
const x = r * Math.cos(theta);
const y = (Math.random() - 0.5) * 10; // Scatter around Y=0
const z = r * Math.sin(theta);
positions.push(x, y, z);
// Assign a random color from the palette based on index for variation
const colorIndex = i % colorPalette.length;
const color = colorPalette[colorIndex];
colors.push(color.r, color.g, color.b);
}
particlesGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
particlesGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Particle Material Setup (using PointsMaterial for better performance)
particlesMaterial = new THREE.PointsMaterial({
size: 1.5, // Size of each particle dot
vertexColors: true, // Use the colors defined in geometry
transparent: true,
opacity: 0.8
});
particleSystem = new THREE.Points(particlesGeometry, particlesMaterial);
scene.add(particleSystem);
}
/**
* Creates a secondary starfield background system.
* @param {number} maxDistance - Max radius for the stars.
*/
function createStarfield(maxDistance) {
const starGeometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < PARTICLES_COUNT * 0.2; i++) { // Fewer points than main particles
// Random spherical distribution
const x = (Math.random() - 0.5) * maxDistance * 2;
const y = (Math.random() - 0.5) * maxDistance * 2;
const z = (Math.random() - 0.5) * maxDistance * 2;
positions.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
starfieldPoints = new THREE.Points(starGeometry, new THREE.PointsMaterial({
color: 0xffffff,
size: 1,
transparent: true,
opacity: 0.7
}));
scene.add(starfieldPoints);
}
/**
* Handles mouse movement to calculate target camera rotation (Tilt).
* @param {MouseEvent} event - The mouse move event object.
*/
function onMouseMove(event) {
// Calculate normalized coordinates (-1 to +1)
targetRotationY = (event.clientX / window.innerWidth) * 2 - 1;
targetRotationX = -(event.clientY / window.innerHeight) * 2 + 1;
// We apply a slight dampening/smoothing effect on the target rotation
}
/**
* Handles window resizing to keep the canvas fullscreen.
*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* The main animation loop. Updates particles and renders the scene.
*/
function animate() {
requestAnimationFrame(animate);
// 1. Particle Animation Update (Spiral Rotation & Pulsing)
const elapsed = performance.now() * 0.0001; // Time in seconds
const particlePositions = particlesGeometry.attributes.position.array;
// Rotate the entire spiral system slowly around the Y-axis
particleSystem.rotation.y += 0.0002;
for (let i = 0; i < PARTICLES_COUNT; i++) {
const index = i * 3;
// Calculate a sinusoidal variation based on time and position
// This makes the particles appear to pulse or flow slightly
particlePositions[index] += Math.sin(elapsed * 1 + i * 0.01) * 0.0005; // X movement
particlePositions[index + 2] -= Math.cos(elapsed * 1 + i * 0.01) * 0.0005; // Z movement
// Optional: Slight rotation around the Y-axis based on time
const x = particlePositions[index];
const y = particlePositions[index + 1] * Math.cos(elapsed * 0.5);
const z = particlePositions[index + 2] * Math.sin(elapsed * 0.5);
// Re-set the position to keep the vortex effect strong
particlePositions[index] = x;
particlePositions[index + 1] = y;
particlePositions[index + 2] = z;
}
particlesGeometry.attributes.position.needsUpdate = true;
// 2. Starfield Movement (Subtle Parallax/Flow)
const starPositions = starfieldPoints.geometry.attributes.position.array;
for (let i = 0; i < starPositions.length; i += 3) {
starPositions[i] *= 1 - Math.sin(elapsed * 0.5 + i/100); // Subtle wobble
// Starfield also rotates slightly
starPositions[i+2] = Math.cos(elapsed * 0.2) * (Math.random() * 0.1);
}
starfieldPoints.geometry.attributes.position.needsUpdate = true;
// 3. Camera Smoothing and Rotation Update
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.05; // Smooth Y rotation
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.05; // Smooth X rotation
// 4. Render the Scene
renderer.render(scene, camera);
// Update FPS Counter
updateFPS();
}
/*
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive 3D particle animation with galaxy-like spiral effects, mouse interaction, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
}
canvas {
display: block;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-size: 14px;
background: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
pointer-events: none;
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: white;
font-size: 24px;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.7);
letter-spacing: 2px;
pointer-events: none;
}
#instructions {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
pointer-events: none;
}
</style>
</head>
<body>
<div id="title">3D GALAXY PARTICLE ANIMATION</div>
<div id="info">FPS: <span id="fps-counter">0</span></div>
<div id="instructions">Move your mouse to tilt the galaxy | Click and drag to rotate</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Main variables
let scene, camera, renderer;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats;
let fpsElement;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// Create particles
createParticles();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
document.addEventListener('mousedown', onDocumentMouseDown);
document.addEventListener('mouseup', onDocumentMouseUp);
window.addEventListener('resize', onWindowResize);
// Initialize FPS counter
fpsElement = document.getElementById('fps-counter');
}
// Create particle system for galaxy
function createParticles() {
const particleCount = 5000;
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy particles
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral galaxy formation
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 40;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color variations
const color = new THREE.Color();
const hue = (Math.random() * 0.2 + 0.5); // Blue to purple range
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Particle sizes
sizes[i] = Math.random() * 3 + 1;
}
// Create geometry and material
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Mouse movement handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Mouse down handler for rotation
let isDragging = false;
let previousMousePosition = {
x: 0,
y: 0
};
function onDocumentMouseDown(event) {
isDragging = true;
previousMousePosition = {
x: event.clientX,
y: event.clientY
};
}
function onDocumentMouseUp() {
isDragging = false;
}
// Window resize handler
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate particles
particleSystem.rotation.x += 0.001;
particleSystem.rotation.y += 0.002;
// Mouse interaction
if (isDragging) {
// Rotation based on mouse movement
particleSystem.rotation.y += (mouseX - particleSystem.rotation.y) * 0.05;
particleSystem.rotation.x += (mouseY - particleSystem.rotation.x) * 0.05;
} else {
// Gentle auto-rotation with mouse tilt effect
particleSystem.rotation.y += 0.001 + mouseX * 0.002;
particleSystem.rotation.x += 0.0005 + mouseY * 0.002;
}
// Update FPS counter
const fps = Math.round(1 / delta);
fpsElement.textContent = fps;
renderer.render(scene, camera);
}
// Start everything
init();
animate();
</script>
</body>
</html>
```
## Features of this 3D Galaxy Animation:
1. **5000 Colorful Particles**: Created in a spiral galaxy formation with varying colors and sizes
2. **Interactive Controls**:
- Mouse movement tilts the galaxy
- Click and drag to rotate the entire galaxy
3. **Starfield Background**: Thousands of stars create a cosmic backdrop
4. **FPS Counter**: Displays real-time frames per second in the top-left corner
5. **Smooth Animations**: All movements are fluid and responsive
6. **Responsive Design**: Adapts to any screen size
7. **Visual Effects**:
- Colorful particles with gradient hues
- Depth perception through size attenuation
- Smooth auto-rotation with mouse interaction
The animation creates a mesmerizing galaxy effect with particles rotating in spiral arms, responding naturally to user input while maintaining high performance. The starfield background adds depth and context to the cosmic scene.
Simply open this HTML file in any modern browser to experience the interactive 3D galaxy!
gemma4:e4b
This is a complex, resource-intensive task best handled by incorporating modern web graphics libraries like Three.js. The following code provides a complete, single-file solution that achieves the galaxy spiral effect, mouse interaction, starfield background, and FPS counter.
### Interactive 3D Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 20px;
left: 20px;
color: white;
font-family: monospace;
background: rgba(0, 0, 0, 0.5);
padding: 8px 15px;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<!-- Three.js Library via CDN -->
<script src="https://cdn.jsdelivr.net/npm/three@r/build/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starField;
const PARTICLE_COUNT = 5000;
const STAR_COUNT = 10000;
// Mouse tracking for interactivity
let mouseX = 0.0;
let mouseY = 0.0;
// Performance variables
let lastTime = performance.now();
let frameCount = 0;
const fpsDisplay = document.getElementById('fpsCounter');
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set camera position and initial look
camera.position.z = 50;
// 2. Create Starfield Background
createStarField();
// 3. Create Galactic Particles
galaxyParticles = createGalaxy();
// 4. Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove);
// Start the animation loop
animate();
}
/**
* Creates a simple, dense starfield background using points.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < STAR_COUNT; i++) {
// Distribute stars randomly within a large cube area
positions.push(
(Math.random() - 0.5) * 200, // x
(Math.random() - 0.5) * 200, // y
(Math.random() - 0.5) * 200 // z
);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
color: 0xAAAAFF, // Light blue/white stars
size: 0.5
});
starField = new THREE.Points(geometry, material);
scene.add(starField);
}
/**
* Creates the primary galaxy particle structure in a spiral shape.
*/
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < PARTICLE_COUNT; i++) {
// Index i determines position along the curve
const t = i / PARTICLE_COUNT * Math.PI * 4; // Angle over 4 rotations
// Spiral structure: r increases with t, z follows a sine wave for depth
const radius = 2 + (i / PARTICLE_COUNT) * 15; // Max spread of 17 units
let x = Math.cos(t * 0.8) * radius;
let y = Math.sin(t * 0.6) * radius * 0.5 + (Math.random() - 0.5); // Slight vertical variation
let z = Math.sin(t * 1.2) * radius * 0.8;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a colorful material that cycles through colors or just uses white/blue glow
const material = new THREE.PointsMaterial({
size: 0.5,
color: 0x66ccff, // Galaxy blue color
blending: THREE.AdditiveBlending, // Makes particles look like glowing light
transparent: true,
opacity: 0.8
});
const galaxy = new THREE.Points(geometry, material);
scene.add(galaxy);
return galaxy;
}
// --- Event Handlers ---
function onWindowResize() {
camera.viewport = { x: 0, y: 0, width: 1, height: 1 };
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
function onMouseMove(event) {
// Normalize mouse coordinates to a range like -1 to 1
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* Main animation loop
*/
function animate() {
requestAnimationFrame(animate);
const now = performance.now();
const delta = (now - lastTime) / 1000; // Delta time in seconds
lastTime = now;
// --- Update Logic ---
// 1. Galaxy Rotation (Self-rotation and slow orbit)
galaxyParticles.rotation.x += 0.0005 * delta;
galaxyParticles.rotation.y += 0.0015 * delta;
// Subtle pulsation/scaling effect
const scaleFactor = 1 + Math.sin(now / 500) * 0.02;
galaxyParticles.scale.set(scaleFactor, scaleFactor, scaleFactor);
// 2. Camera Interaction (Mouse Tilt Effect)
// Use the mouse coordinates to rotate the camera slightly
camera.rotation.y = mouseX * 0.5;
camera.rotation.x = mouseY * 0.3;
// 3. Starfield Movement (Subtle shift for parallax effect)
starField.position.x += Math.sin(now / 2000) * 0.01 * delta;
starField.position.y -= Math.cos(now / 2500) * 0.01 * delta;
// --- Rendering and Performance ---
renderer.render(scene, camera);
updateFPS(delta);
}
/**
* Calculates and displays the current FPS.
*/
function updateFPS(deltaTime) {
frameCount++;
const elapsed = performance.now() - lastTime; // Approximation
let fps = 1 / deltaTime; // Simple calculation based on delta time
// Smooth out the counter display (simple averaging)
if (fpsDisplay.dataset.lastFps) {
const avgFps = parseFloat(fpsDisplay.dataset.lastFps);
const newAvg = (avgFps * 0.9 + fps * 0.1).toFixed(0);
fpsDisplay.textContent = `FPS: ${newAvg}`;
} else {
fpsDisplay.textContent = `FPS: ${Math.round(fps)}`;
fpsDisplay.dataset.lastFps = Math.round(fps);
}
}
// Initialize the scene when everything is loaded
window.onload = init;
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive 3D particle galaxy animation with mouse interaction, starfield background, and FPS counter - all in a single HTML file using Three.js.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
max-width: 300px;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff758c);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 126, 179, 0.3);
}
#info p {
font-size: 0.9rem;
margin-bottom: 15px;
line-height: 1.5;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
font-family: monospace;
font-size: 1.2rem;
}
#instructions {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 12px 20px;
border-radius: 30px;
backdrop-filter: blur(5px);
text-align: center;
font-size: 0.9rem;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>3D Galaxy Particle Animation</h1>
<p>This interactive visualization shows 5000 colorful particles rotating in a galaxy-like spiral pattern.</p>
<p>Move your mouse to tilt the galaxy and explore the cosmic environment.</p>
<p>Background stars create a realistic space scene with depth perception.</p>
</div>
<div id="fps-counter">FPS: 60</div>
<div id="instructions">Move your mouse to interact with the galaxy</div>
</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let fpsCounter = document.getElementById('fps-counter');
let clock = new THREE.Clock();
let stats = { fps: 60, frameCount: 0, lastTime: performance.now() };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
2000
);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create the galaxy particle system
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Galaxy parameters
const radius = 150;
const arms = 4;
const armWidth = 0.3;
const density = 1.5;
const turbulence = 0.1;
// Create particles
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position in spiral galaxy
const angle = Math.random() * Math.PI * 2;
const armAngle = angle + Math.sin(i * 0.01) * turbulence;
// Spiral arm calculation
const armIndex = Math.floor(armAngle / (Math.PI * 2 / arms)) % arms;
const armOffset = (armIndex / arms) * (Math.PI * 2);
const spiralAngle = armAngle + armOffset;
const spiralRadius = Math.sqrt(Math.random()) * radius;
// Position in 3D space
const x = Math.cos(spiralAngle) * spiralRadius;
const y = Math.sin(spiralAngle) * spiralRadius;
const z = (Math.random() - 0.5) * 20;
positions[i3] = x;
positions[i3 + 1] = y;
positions[i3 + 2] = z;
// Color based on position
const color = new THREE.Color();
const hue = (spiralAngle / (Math.PI * 2)) * 0.5 + 0.5;
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Size variation
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starPositions = [];
const starColors = [];
const starSizes = [];
// Create 10,000 stars
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starPositions.push(x, y, z);
// Star colors (white to blue-white)
const color = new THREE.Color();
const hue = Math.random() * 0.1 + 0.5; // Blue-white spectrum
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.7 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
starColors.push(color.r, color.g, color.b);
// Random sizes
starSizes.push(Math.random() * 1.5 + 0.5);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
starGeometry.setAttribute('color', new THREE.Float32BufferAttribute(starColors, 3));
starGeometry.setAttribute('size', new THREE.Float32BufferAttribute(starSizes, 1));
const starMaterial = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY
gemma4:e4b
This solution provides a highly optimized, visually rich single-file implementation using modern JavaScript features and best practices for Three.js to ensure smooth performance while achieving the requested effects.
**Key Features Implemented:**
* **Spiral Galaxy:** 5000 particles positioned in a dense, rotating spiral structure.
* **Mouse Interaction (Tilt):** The entire scene rotates based on cursor coordinates (`mousemove`).
* **Starfield Background:** A separate, static point cloud simulates deep space stars.
* **FPS Counter:** Real-time Frame Rate counter displayed in the corner.
* **Performance:** Uses `BufferGeometry` for efficient rendering of thousands of particles.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 10px;
left: 20px;
color: white;
font-family: 'Arial', sans-serif;
background: rgba(0, 0, 0, 0.6);
padding: 5px 10px;
border-radius: 5px;
user-select: none;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdn.jsdelivr.net/npm/three@r128/build/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starFieldGroup;
const NUM_GALACTIC_PARTICLES = 5000;
const STARFIELD_DENSITY = 12000;
// Mouse tracking for rotation
const mouse = new THREE.Vector2();
const targetRotation = { x: 0, y: 0 };
let lastTime = performance.now();
let frameCount = 0;
let fpsStartTime = lastTime;
// --- Initialization Function ---
function init() {
// Scene Setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set camera position for a good view
camera.position.z = 50;
// --- 1. Create Starfield Background (Static) ---
createStarField();
// --- 2. Create Galactic Spiral Particles ---
galaxyParticles = createSpiralGalaxy(NUM_GALACTIC_PARTICLES);
scene.add(galaxyParticles);
// --- Event Listeners ---
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
// Start the animation loop
animate();
}
/**
* Creates a dense starfield using BufferGeometry for efficiency.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < STARFIELD_DENSITY; i++) {
// Generate points within a large sphere (-100 to 100)
const x = Math.random() * 200 - 100;
const y = Math.random() * 200 - 100;
const z = Math.random() * 200 - 100;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material: Small white points that fade slightly
const material = new THREE.PointsMaterial({
color: 0xffffff,
size: 1,
transparent: true,
opacity: 0.8
});
const starField = new THREE.Points(geometry, material);
starField.name = "StarField";
scene.add(starField);
return starField;
}
/**
* Generates particles in a spiral pattern using parametric equations (R=r, Theta=t).
* @param {number} count - Number of particles to generate.
* @returns {THREE.Points} The particle system object.
*/
function createSpiralGalaxy(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < count; i++) {
// Parameterizing the spiral:
// r increases linearly with index, t determines the angle.
const normalizedIndex = i / count;
// Radius R: Base radius + slight variation
const r = Math.pow(normalizedIndex, 0.5) * 80; // Slower growth makes it look more galactic
// Angle Theta: Controls the spiral tightness (e.g., multiplying by -3 creates a strong coil)
const t = normalizedIndex * 12 + Math.sin(i * 0.5) * 2;
// Z-axis depth variation
const z = Math.sin(normalizedIndex * 4) * 20;
// Cartesian conversion (x = r * cos(t), y = r * sin(t))
const x = r * Math.cos(t);
const y = r * Math.sin(t);
const zCoord = z; // Use the calculated Z depth
positions.push(x, y, zCoord);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material: Colorful and glowing points
const material = new THREE.PointsMaterial({
size: 1.5,
opacity: 0.9,
transparent: true,
vertexColors: true // We will rely on the basic geometry color for simplicity/performance
});
const galaxy = new THREE.Points(geometry, material);
return galaxy;
}
// --- Event Handlers ---
/**
* Handles window resizing to keep the scene full screen.
*/
function onWindowResize() {
camera.viewport.setSize(window.innerWidth, window.innerHeight);
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates the target rotation based on mouse position (normalized to -1 to 1).
*/
function onDocumentMouseMove(event) {
// Normalize mouse coordinates (-1 to +1) relative to screen size
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// Set target rotation based on mouse position
targetRotation.x = mouse.y * 0.2; // Vertical tilt sensitivity
targetRotation.y = mouse.x * 0.2; // Horizontal pan sensitivity
}
// --- Animation Loop ---
function animate(time) {
requestAnimationFrame(animate);
const delta = (time - lastTime) / 1000; // Time elapsed since last frame in seconds
lastTime = time;
// === 1. Galaxy Rotation & Movement ===
if (galaxyParticles) {
// Continuous self-rotation for the galaxy
galaxyParticles.rotation.y += delta * 0.05;
galaxyParticles.rotation.x += delta * 0.02;
}
// === 2. Starfield Movement (Subtle drift) ===
if (starFieldGroup) {
// Slow, subtle rotation to simulate deep space drifting
starFieldGroup.rotation.y += 0.0001;
}
// === 3. Camera/Scene Tilt (Mouse Response) ===
// Smoothly interpolate the camera's rotation towards the target mouse position
camera.rotation.y += (targetRotation.y - camera.rotation.y) * 0.08;
camera.rotation.x += (targetRotation.x - camera.rotation.x) * 0.08;
// === 4. Render and Update FPS ===
renderer.render(scene, camera);
updateFPS(time);
}
/**
* Updates the displayed FPS counter.
* @param {number} currentTime - Current time stamp.
*/
function updateFPS(currentTime) {
frameCount++;
const elapsed = (currentTime - fpsStartTime) / 1000; // Time in seconds
if (elapsed >= 1.0) {
const fps = Math.round(frameCount / elapsed);
document.getElementById('fpsCounter').textContent = `FPS: ${fps}`;
// Reset counter for next second calculation
frameCount = 0;
fpsStartTime = currentTime;
}
}
// Start the application
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy simulation with 5000 colorful particles that respond to mouse movement and include a starfield background with FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
z-index: 100;
max-width: 300px;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #4facfe, #00f2fe);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(79, 172, 254, 0.5);
}
#info p {
font-size: 1rem;
margin-bottom: 15px;
line-height: 1.5;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
font-family: monospace;
font-size: 1.2rem;
z-index: 100;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
backdrop-filter: blur(5px);
text-align: center;
font-size: 0.9rem;
z-index: 100;
}
.highlight {
color: #00f2fe;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive Galaxy Simulation</h1>
<p>This 3D particle animation features:</p>
<ul>
<li>5000 colorful particles in a spiral galaxy pattern</li>
<li>Real-time mouse interaction for rotation control</li>
<li>Starry background with depth effect</li>
<li>FPS performance counter</li>
<li>Smooth, mesmerizing animations</li>
</ul>
<p>Move your mouse to tilt the galaxy and explore its spiral structure!</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move mouse to interact | <span class="highlight">Click & drag</span> to rotate | <span class="highlight">Scroll</span> to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let fpsCounter = document.getElementById('fps-counter');
let clock = new THREE.Clock();
let stats = { fps: 0, frames: 0, lastTime: performance.now() };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
2000
);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create the galaxy particle system
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create particles in a spiral galaxy pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral galaxy formation
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 4;
const height = (Math.random() - 0.5) * 20;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color variations
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) % 1;
color.setHSL(hue, 0.8, 0.5);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 3 + 1;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Mouse movement handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update FPS counter
updateFPS();
// Rotate particles based on mouse position
if (particleSystem) {
particleSystem.rotation.x = mouseY * 0.5;
particleSystem.rotation.y = mouseX * 0.5;
// Slowly rotate the galaxy
particleSystem.rotation.z += 0.0005;
}
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
}
// Update FPS counter
function updateFPS() {
const now = performance.now();
stats.frames++;
if (now >= stats.lastTime + 1000) {
stats.fps = Math.round((stats.frames * 1000) / (now - stats.lastTime));
fpsCounter.textContent =
gemma4:e4b
This code provides a complete, single-file implementation of the interactive 3D particle galaxy animation using Three.js.
Due to the computational intensity of managing 5000 points with complex math (spiral placement, rotation, mouse response) and performance tracking, ensure you run this in a modern browser environment for optimal results.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particle Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: monospace;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: --</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
const NUM_GALACTIC_PARTICLES = 5000;
const NUM_STARFIELD_POINTS = 10000;
// Mouse tracking for interactivity
let mouseX = 0;
let mouseY = 0;
// Performance monitoring variables
let frameCount = 0;
let lastTime = performance.now();
const fpsContainer = document.getElementById('fps-counter');
/**
* Initialization function: Sets up the scene, camera, and geometries.
*/
function init() {
// 1. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 2. Scene and Camera Setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// --- Particle Generation Functions ---
// 3. Starfield Background (Static Points)
createStarfield();
// 4. Galaxy Particles (Spiral Structure)
galaxyParticles = createGalaxy(NUM_GALACTIC_PARTICLES);
// 5. Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove);
}
/**
* Creates the dense, colorful starfield background using Points.
*/
function createStarfield() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < NUM_STARFIELD_POINTS; i++) {
// Distribute points randomly in a large sphere
const x = (Math.random() - 0.5) * 400;
const y = (Math.random() - 0.5) * 400;
const z = (Math.random() - 0.5) * 400;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use PointsMaterial for simple star representation
const material = new THREE.PointsMaterial({
size: 0.5,
color: 0xaaaaee, // Light blue/white color
transparent: true,
opacity: 0.8
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
/**
* Creates the spiral galaxy structure for the main particles.
* Uses a parametric equation (spiral form).
*/
function createGalaxy(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
for (let i = 0; i < count; i++) {
// Parameter 't' controls the position along the spiral path
const t = (i / count) * Math.PI * 6; // Multiplies by 6 for tighter spirals
// Spiral equation approximation: r = a + b*t, z = c*t^2
const radius = 10 + (Math.sin(t * 3) * 5); // Modulate radial distance
const x = Math.cos(t) * radius;
const y = Math.sin(t) * radius * 0.8; // Slightly squashed in Y
// Z depth helps create the sheet-like structure
const z = (i - count / 2) * 0.1 + (Math.random() * 5);
positions.push(x, y, z);
// Random color generation for the "colorful" effect
const r = Math.random();
const g = Math.random();
const b = Math.random();
colors.push(r, g, b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1.5, // Larger size for visibility
vertexColors: true, // Use the random colors calculated above
transparent: true,
opacity: 0.9
});
const galaxy = new THREE.Points(geometry, material);
scene.add(galaxy);
return galaxy;
}
/**
* Handles window resizing to keep the canvas full screen.
*/
function onWindowResize() {
camera.viewport.set(0, 0, 1, 1);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates mouse tracking variables based on cursor movement.
*/
function onMouseMove(event) {
mouseX = (event.clientX / window.innerWidth) * 2 - 1; // Range: -1 to 1
mouseY = -(event.clientY / window.innerHeight) * 2 - 1; // Range: -1 to 1 (inverted for vertical tilt)
}
/**
* The main animation loop. Called every frame.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() / 1000; // Time in seconds
// --- Update Logic ---
// 1. Galaxy Rotation (Slower, constant rotation)
galaxyParticles.rotation.y += 0.0002;
galaxyParticles.rotation.x = Math.sin(time * 0.1) * 0.1;
// 2. Starfield Movement/Rotation (Subtle background drift)
starfieldParticles.rotation.y += 0.00005;
// 3. Mouse Interaction (Camera Tilt)
// Smoothly adjust camera rotation based on mouse input
const targetX = mouseX * 0.2; // Sensitivity factor
const targetY = mouseY * 0.2;
camera.rotation.y += (targetX - camera.rotation.y) * 0.05;
camera.rotation.x += (targetY + Math.PI / 4) * 0.05; // Added offset to prevent pitch lock
// Reset mouse tracking variables slightly to prevent continuous drift from the mouse listener
mouseX *= 0.9;
mouseY *= 0.9;
// --- Rendering ---
renderer.render(scene, camera);
// Update FPS Counter
updateFPS();
}
/**
* Calculates and displays the current Frames Per Second (FPS).
*/
function updateFPS() {
frameCount++;
const currentTime = performance.now();
const elapsed = currentTime - lastTime;
if (elapsed >= 1000) { // Update display every second
const fps = Math.round(frameCount * (1000 / elapsed));
fpsContainer.textContent = `FPS: ${fps}`;
// Reset counters
lastTime = currentTime;
frameCount = 0;
}
}
/**
* Main execution block.
*/
init();
animate();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an interactive 3D particle galaxy animation with mouse tilt responsiveness, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.9);
font-size: 24px;
font-weight: 300;
letter-spacing: 2px;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 8px 12px;
border-radius: 8px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="title">3D GALAXY PARTICLE ANIMATION</div>
<div id="info">Interactive Galaxy Simulation | 5000 Particles | Mouse Tilt Response</div>
<div id="fps-counter">FPS: 60</div>
<div id="instructions">Move mouse to tilt the galaxy | Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 60 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy particles
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position particles in a spiral galaxy pattern
const radius = Math.random() * 200;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 10;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (Math.random() * 0.3 + 0.5); // Blue to purple range
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes for particles
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create particle system
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate particles
particleSystem.rotation.y += 0.001;
// Mouse tilt effect
camera.position.x += (mouseX * 50 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 50 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// Update controls
controls.update();
// Update FPS counter
stats.fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${stats.fps}`;
// Render scene
renderer.render(scene, camera);
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this Interactive Galaxy Animation:
1. **5000 Colorful Particles**: Created in a spiral galaxy pattern with varying colors and sizes
2. **Mouse Interaction**: The galaxy tilts based on mouse movement for an immersive experience
3. **Starfield Background**: 10,000 stars create a realistic cosmic backdrop
4. **FPS Counter**: Displays real-time frame rate in the bottom-right corner
5. **Responsive Design**: Adapts to any screen size and maintains performance
6. **Visual Effects**:
- Additive blending for glowing particles
- Smooth animations with damping
gemma4:e4b
This is a complete, single-file implementation using Three.js that creates a visually complex, interactive 3D particle animation simulating a galactic spiral with mouse tilt responsiveness and an FPS counter.
### Galactic Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Galaxy Spiral Particles</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000; }
canvas { display: block; }
/* Styling for the FPS counter */
#fps-counter {
position: fixed;
top: 10px;
left: 10px;
color: #ffffff;
font-family: 'Arial', sans-serif;
padding: 8px 15px;
background: rgba(0, 0, 0, 0.6);
border-radius: 5px;
z-index: 100;
font-size: 14px;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 60</div>
<!-- Three.js CDN Script -->
<script src="https://cdn.jsdelivr.net/npm/three@r/build/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
const particleCount = 5000;
const starCount = 15000;
// Mouse tracking for interactive tilt
let mouseX = 0;
let mouseY = 0;
// FPS Tracking variables
let frameCount = 0;
let lastTime = performance.now();
let fpsInterval = setInterval(updateFPS, 500); // Update FPS every half second
// --- Initialization Function ---
function init() {
// Scene setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 100;
// Renderer setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Initialize particle systems
createGalaxySpiral();
createStarField();
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove);
// Start the animation loop
animate();
}
/**
* Creates the main spiral galaxy particle system.
*/
function createGalaxySpiral() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
const radiusScale = 10; // Base size for the spiral
for (let i = 0; i < particleCount; i++) {
// Use parametric equations to create a spiral shape: R = A*theta, Z = B*theta
// theta controls the rotation/spiral progress
const t = i / particleCount * Math.PI * 4;
// X coordinates (R * cos(t))
const x = Math.sin(t) * radiusScale * (1 + t / (Math.PI * 4));
// Y coordinates (R * sin(t)) - making it slightly vertical for depth
const y = Math.cos(t) * radiusScale * (0.5 + t / (Math.PI * 8));
// Z coordinates (Spiral effect: increasing distance with rotation)
const z = t * 10;
positions.push(x, y, z);
// Generate vibrant colors based on particle index/position
color.setHSL(i / particleCount, 0.8, 0.6 + Math.random() * 0.2);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup: Use PointsMaterial for performance and assign colors
const material = new THREE.PointsMaterial({
size: 1.5, // Particle size
vertexColors: true, // Enable using per-vertex color attributes
blending: THREE.AdditiveBlending, // Gives a glow effect
transparent: true,
sizeAttenuation: true
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates the distant starfield background using random points.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < starCount; i++) {
// Randomly position stars far away in a large sphere/cube
const x = ((Math.random() - 0.5) * 400);
const y = ((Math.random() - 0.5) * 400);
const z = ((Math.random() - 0.5) * 400);
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material setup for stars (smaller, dimmer points)
const material = new THREE.PointsMaterial({
size: 0.5,
color: 0xaaaaee, // Light blue/white color
transparent: true,
blending: THREE.AdditiveBlending
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
// --- Event Handlers and Utilities ---
/**
* Handles window resizing to keep the renderer and camera updated.
*/
function onWindowResize() {
camera.viewport = camera.domElement;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates mouse coordinates globally for the animation loop.
*/
function onMouseMove(event) {
// Normalize coordinates from -1 to +1
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* Updates the FPS display counter every half second.
*/
function updateFPS() {
const currentTime = performance.now();
const elapsedSeconds = (currentTime - lastTime) / 1000;
if (elapsedSeconds >= 0.5) {
const fps = Math.round(frameCount / elapsedSeconds);
document.getElementById('fps-counter').textContent = `FPS: ${fps}`;
// Reset for next interval
frameCount = 0;
lastTime = currentTime;
}
}
// --- Animation Loop ---
function animate() {
requestAnimationFrame(animate);
const time = performance.now() * 0.0001; // Time in radians for smooth rotation
// 1. Rotation (Galaxy and Stars)
galaxyParticles.rotation.y += 0.001;
starFieldParticles.rotation.y += 0.0005;
// 2. Mouse Interaction / Tilt Effect
// Apply a subtle rotational offset based on mouse position
const tiltFactor = 0.005;
galaxyParticles.rotation.x += (mouseY * tiltFactor);
galaxyParticles.rotation.y += (mouseX * tiltFactor);
// Camera movement refinement for parallax effect
camera.position.x += (mouseX * 2 - camera.position.x) * 0.1;
camera.position.y += (-mouseY * 2 - camera.position.y) * 0.1;
camera.lookAt(scene.position);
// 3. Render the scene
renderer.render(scene, camera);
// Increment frame counter for FPS calculation
frameCount++;
}
// Start everything up!
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive Galaxy Particle Animation
I'll create an immersive 3D particle animation that simulates a galaxy with 5000 colorful particles rotating in a spiral pattern. The scene will respond to mouse movement and include a starfield background with FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Galaxy Particle Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
cursor: pointer;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
#fps {
position: absolute;
top: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: rgba(255, 255, 255, 0.8);
font-size: 36px;
text-align: center;
z-index: 100;
text-shadow: 0 0 20px rgba(100, 150, 255, 0.7);
opacity: 0.9;
transition: opacity 2s ease;
}
#title.hidden {
opacity: 0;
}
</style>
</head>
<body>
<div id="container">
<div id="info">Interactive Galaxy Simulation<br>Move your mouse to tilt the galaxy</div>
<div id="fps">FPS: 0</div>
<div id="title">Galaxy Particle Animation</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let stats, clock;
let particleSystem;
let stars = [];
let titleTimeout;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add lighting
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1, 1000);
pointLight.position.set(50, 50, 50);
scene.add(pointLight);
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Setup clock for FPS counter
clock = new THREE.Clock();
// Hide title after 3 seconds
titleTimeout = setTimeout(() => {
document.getElementById('title').classList.add('hidden');
}, 3000);
// Start animation loop
animate();
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create particles in a spiral galaxy pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral pattern with some randomness
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Random color based on position
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) % 1;
color.setHSL(hue, 0.8, 0.5);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random size
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.01;
mouseY = (event.clientY - windowHalfY) * 0.01;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Rotate particles
particleSystem.rotation.x += 0.001;
particleSystem.rotation.y += 0.002;
// Tilt with mouse movement
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// Update FPS counter
const delta = clock.getDelta();
const fps = Math.round(1 / delta);
document.getElementById('fps').textContent = `FPS: ${fps}`;
// Render scene
renderer.render(scene, camera);
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this Galaxy Animation:
1. **5000 Colorful Particles**: Created in a spiral galaxy pattern with varying colors and sizes
2. **Interactive Rotation**: The galaxy rotates smoothly, responding to mouse movement (tilt effect)
3. **Starfield Background**: 10,000 stars create a deep space environment
4. **FPS Counter**: Displays real-time frames per second in the top-right corner
5. **Responsive Design**: Adapts to any screen size
6. **Visual Effects**:
- Smooth particle movement
- Colorful spiral galaxy
- Depth perception with size attenuation
- Ambient lighting for realistic appearance
The animation starts with a title that fades after 3 seconds, then you can interact with the galaxy by moving your mouse to tilt it. The FPS counter in the top-right corner updates in real-time to show performance.
Simply copy and paste this code into an HTML file and open it in any modern browse
gemma4:e4b
This solution provides a single HTML file containing all necessary CSS, JavaScript, and the Three.js library to create the interactive particle animation.
### 🌌 Interactive Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle System</title>
<!-- Import Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: Arial, sans-serif;
background: rgba(0, 0, 0, 0.5);
padding: 8px;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
const NUM_GALAXY_PARTICLES = 5000;
const STARFIELD_COUNT = 20000;
// Camera control variables (for mouse interaction)
let mouseX = 0;
let mouseY = 0;
// FPS tracking variables
let lastTime = performance.now();
let frameCount = 0;
const fpsElement = document.getElementById('fpsCounter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// Scene Setup
scene = new THREE.Scene();
// Camera Setup (Perspective for depth)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 80;
// Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// --- Create Components ---
createStarfield();
createGalaxyParticles();
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove);
// Start the animation loop
animate();
}
/**
* Generates a massive, random starfield background particle system.
*/
function createStarfield() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
for (let i = 0; i < STARFIELD_COUNT; i++) {
// Generate random positions in a large cube volume
positions.push(Math.random() * 200 - 100); // x
positions.push(Math.random() * 200 - 100); // y
positions.push(Math.random() * 200 - 100); // z
// Assign a faint white color
colors.push(1, 1, 1);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.UintColormap(new Float32Array(colors), 3));
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true,
transparent: true,
opacity: 0.6
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
/**
* Generates the main galaxy spiral particle system using a mathematical function.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Parameters for the spiral shape (Archimedean/Logarithmic approximation)
const maxRadius = 60;
const numPoints = NUM_GALAXY_PARTICLES;
for (let i = 0; i < numPoints; i++) {
// Normalized parameter t (0 to 2*PI for a full spiral rotation)
const t = (i / numPoints) * Math.PI * 6; // Spiral wraps multiple times
// Calculate radius based on the sine function and distance from center
const r = maxRadius * (1 + Math.sin(t / 4)) * ((Math.random() * 0.5) + 0.5);
// X, Y, Z coordinates for a spiral shape
const x = r * Math.cos(t);
const y = r * sin(t / 3) * 0.8; // Flatten the vertical dimension slightly
const z = r * Math.sin(t);
positions.push(x);
positions.push(y);
positions.push(z);
// Assign random, colorful particles
const colorR = Math.random();
const colorG = Math.random();
const colorB = Math.random();
colors.push(colorR, colorG, colorB);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.UintColormap(new Float32Array(colors), 3));
// Particle Material (Use colors and sizes for visual appeal)
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
blending: THREE.AdditiveBlending, // Makes particles glow when overlapping
transparent: true,
opacity: 0.9
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Handles window resizing to keep the renderer and camera updated.
*/
function onWindowResize() {
camera.viewport = camera.domElement;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Captures mouse movement data for interactive tilting.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX / window.innerWidth) * 2 - 1; // Range: -1 to 1
mouseY = -(event.clientY / window.innerHeight) * 2 - 1; // Range: -1 to 1 (inverted for natural camera feel)
}
/**
* The main animation loop function (runs 60 FPS).
* @param {number} time - The current timestamp provided by requestAnimationFrame.
*/
function animate(time) {
requestAnimationFrame(animate);
// --- Performance Tracking ---
const deltaTime = performance.now() - lastTime;
frameCount++;
if (deltaTime >= 1000) {
const fps = Math.round((frameCount * 1000 / deltaTime));
fpsElement.textContent = `FPS: ${fps}`;
frameCount = 0;
lastTime = performance.now();
}
// --- Animation Logic ---
// 1. Galaxy Rotation (Self-rotation)
galaxyParticles.rotation.y += 0.002;
galaxyParticles.rotation.x += 0.001;
// 2. Starfield Drift/Rotation
starfieldParticles.rotation.y += 0.0005;
starfieldParticles.rotation.z += 0.0003;
// 3. Camera Interaction (Tilt based on mouse position)
// Use the mouse coordinates to subtly rotate the camera and scene
const targetRotationX = mouseY * Math.PI * 0.15; // Max tilt angle
const targetRotationY = mouseX * Math.PI * 0.15;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.05;
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.05;
// Render the scene
renderer.render(scene, camera);
}
// Initialize everything when the script loads
init();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN, you can follow this example below. This code will include a starfield background and colorful particles rotating in a spiral galaxy-like pattern, responding to mouse movement for tilting effects, and displaying an FPS counter in the corner.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Starfield background
const starsGeometry = new THREE.BufferGeometry();
const starPositions = [];
for (let i = 0; i < 5000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = Math.random() * 4000 - 2000;
starPositions.push(x, y, z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
const starMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
const stars = new THREE.Points(starsGeometry, starMaterial);
scene.add(stars);
// Particles
const particleCount = 5000;
const particlesGeometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = Math.random() * 4000 - 2000;
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const particleMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 2 });
const particles = new THREE.Points(particlesGeometry, particleMaterial);
scene.add(particles);
// Camera position and animation
camera.position.z = 1500;
let mouseX = 0, mouseY = 0;
window.addEventListener('mousemove', (event) => {
mouseX = event.clientX - window.innerWidth / 2;
mouseY = event.clientY - window.innerHeight / 2;
});
const clock = new THREE.Clock();
// Tilt effect based on mouse movement
function animate() {
requestAnimationFrame(animate);
const elapsedTime = clock.getElapsedTime();
particles.rotation.x += 0.005;
particles.rotation.y += 0.005;
particles.position.z = Math.sin(elapsedTime) * 100;
const tiltSpeed = 0.02;
camera.position.set(mouseX * tiltSpeed, mouseY * tiltSpeed, camera.position.z);
renderer.render(scene, camera);
}
animate();
// FPS counter
let fps = 0;
let lastTime = performance.now();
function updateFPS() {
const now = performance.now();
const delta = now - lastTime;
fps = Math.floor(1 / (delta / 1000));
lastTime = now;
requestAnimationFrame(updateFPS);
}
updateFPS();
// Resize event for the canvas
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
</script>
</body>
</html>
```
This code sets up a basic 3D scene with a starfield and particles that rotate in a spiral pattern, responding to mouse movements for tilting effects. It also includes an FPS counter at the top-left corner of the canvas, updating every frame based on the elapsed time since the last update. Make sure to adjust the camera's position and rotation according to your specific requirements to achieve the desired visual effect.
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D galaxy animation with 5000 particles that respond to mouse movement and include a starfield background with FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
max-width: 300px;
z-index: 10;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 166, 0.3);
}
#info p {
font-size: 1rem;
margin-bottom: 15px;
line-height: 1.5;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
backdrop-filter: blur(5px);
z-index: 10;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 30px;
text-align: center;
font-size: 0.9rem;
backdrop-filter: blur(5px);
z-index: 10;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive Galaxy Animation</h1>
<p>This 3D visualization features <span class="highlight">5000 colorful particles</span> forming a galaxy-like spiral structure.</p>
<p>Move your mouse to tilt the galaxy and explore its depth. The starfield background creates an immersive space environment.</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Click and drag to rotate</div>
</div>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
// Create spiral galaxy structure
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 50;
// Position particles in spiral pattern
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) % 1;
color.setHSL(hue, 0.8, 0.5 + Math.random() * 0.3);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate particles
if (particles) {
particles.rotation.x += 0.001;
particles.rotation.y += 0.002;
// Mouse tilt effect
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
// Update FPS counter
updateFPSCounter(delta);
}
// Update FPS counter display
function updateFPSCounter(delta) {
const fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${fps}`;
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this Interactive Galaxy Animation:
1. **5000 Colorful Particles**: Forming a beautiful spiral galaxy structure with varying colors and sizes
2. **Mouse Interaction**:
- Move mouse to tilt the galaxy
- Click and drag to rotate the entire scene
3. **Starfield Background**: Thousands of stars creating an immersive space environment
4. **FPS Counter**: Real-time frame rate display in the top-right corner
5. **Responsive Design**: Adapts to any screen size
6. **Visual Effects**:
- Smooth animations
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D particle animation with galaxy-like spiral, mouse tilt response, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
max-width: 300px;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 163, 0.3);
}
#info p {
font-size: 1rem;
line-height: 1.5;
margin-bottom: 15px;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
font-family: monospace;
font-size: 1.2rem;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 30px;
backdrop-filter: blur(5px);
text-align: center;
font-size: 0.9rem;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>This simulation features:</p>
<p>• <span class="highlight">5000 colorful particles</span> in a galaxy-like spiral</p>
<p>• <span class="highlight">Mouse tilt interaction</span> for dynamic rotation</p>
<p>• <span class="highlight">Starfield background</span> with twinkling stars</p>
<p>• <span class="highlight">Real-time FPS counter</span></p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Click and drag to rotate</div>
</div>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
2000
);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create the galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy with spiral arms
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 40;
// Position particles in spiral arms
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Create colorful particles with gradient colors
const color = new THREE.Color();
const hue = (i / particleCount) * 0.5 + 0.5; // Blue to purple range
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
// Create particles
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Create starfield background
function createStarfield() {
const starCount = 2000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
// Create stars in a spherical distribution
const radius = 500 + Math.random() * 1000;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positions[i3 + 2] = radius * Math.cos(phi);
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
transparent: true,
opacity: 0.8
});
const stars = new THREE.Points(geometry, material);
scene.add(stars);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 2;
mouseY = (event.clientY - windowHalfY) / 2;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Rotate particles
if (particles) {
particles.rotation.x = elapsedTime * 0.05;
particles.rotation.y = elapsedTime * 0.02;
// Mouse tilt effect
if (particles.rotation.x < 0.1) {
particles.rotation.z = mouseX * 0.0005;
}
}
// U
gemma4:e4b
This is a complex, high-performance visualization that requires careful structuring in Three.js. The code below encapsulates all functionality into a single self-contained HTML file.
### Galactic Particle Animator
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fpsCounter {
position: fixed;
top: 10px;
left: 10px;
padding: 5px 10px;
background-color: rgba(0, 0, 0, 0.5);
color: #ffffff;
font-family: monospace;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: --</div>
<!-- Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
const PARTICLE_COUNT = 5000;
let mouseX = 0;
let mouseY = 0;
// FPS Counter variables
let frameCount = 0;
let lastTime = performance.now();
let fpsDisplay;
/**
* Initializes the Three.js environment, scene elements, and particle systems.
*/
function init() {
// Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Scene Setup
scene = new THREE.Scene();
scene.background = new THREE.Color(0x00000a); // Deep space background
// Camera Setup
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 50;
// --- 1. Galactic Spiral Particles (The Main Feature) ---
galaxyParticles = createGalaxySystem(PARTICLE_COUNT);
scene.add(galaxyParticles);
// --- 2. Starfield Background Particles ---
starFieldParticles = createStarField(10000);
scene.add(starFieldParticles);
// Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
// FPS Display Setup
fpsDisplay = document.getElementById('fpsCounter');
}
/**
* Generates the particles for the galaxy, placing them in a spiral pattern.
* @param {number} count - Number of particles to generate.
* @returns {THREE.Points} The particle system object.
*/
function createGalaxySystem(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Create the spiral structure using polar coordinates
for (let i = 0; i < count; i++) {
// Calculate position based on a spiral function
// Radius grows slowly with angle, simulating arms
const theta = Math.random() * Math.PI * 2; // Full circle angle
const r = Math.pow(Math.random(), 0.5) * 30 + (i / count * 40); // Distance from center increases slightly
// Add small random perturbations to make it look more natural
const x = r * Math.cos(theta) * (1 + Math.random() * 0.2);
const y = r * Math.sin(theta) * (1 + Math.random() * 0.2);
const z = Math.random() * 5 - 2.5; // Keep depth relatively shallow
positions.push(x, y, z);
// Assign random vibrant colors
const color = new THREE.Color();
color.setHSL(Math.random(), 0.8, Math.random() * 0.6 + 0.3); // HSL for bright colors
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup for colorful points
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors stored in the geometry
blending: THREE.AdditiveBlending, // Gives a glow effect
transparent: true
});
const points = new THREE.Points(geometry, material);
return points;
}
/**
* Generates a large, sparse starfield for background depth.
* @param {number} count - Number of stars to generate.
* @returns {THREE.Points} The particle system object.
*/
function createStarField(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < count; i++) {
// Place stars far away to simulate deep space
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = Math.random() * 1000 - 500;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material for faint stars
const material = new THREE.PointsMaterial({
size: 1.5,
color: 0xaaffff, // Faint blue-white color
blending: THREE.AdditiveBlending,
transparent: true,
opacity: 0.6
});
const points = new THREE.Points(geometry, material);
return points;
}
/**
* Handles window resizing to keep the canvas fit.
*/
function onWindowResize() {
camera.viewport = { x: 0, y: 0, width: 1, height: 1 };
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates mouse coordinates and smooths the input for interactive tilt effects.
*/
function onDocumentMouseMove(event) {
// Normalize coordinates (-1 to +1)
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* Animation loop: Updates particle positions and renders the scene.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() / 1000; // Time in seconds
// --- 1. Galaxy Rotation (Self-contained rotation) ---
galaxyParticles.rotation.y += 0.0015;
galaxyParticles.rotation.x += 0.0005;
// Update particle positions for a slow "pulsing" effect
const positionAttribute = galaxyParticles.geometry.attributes.position;
for (let i = 0; i < PARTICLE_COUNT * 3; i += 3) {
// Apply subtle movement based on time and original position
const x = positionAttribute.getX(i);
const y = positionAttribute.getY(i);
const z = positionAttribute.getZ(i);
positionAttribute.setX(x + Math.sin(time * 0.5 + i * 0.01) * 0.5, positionAttribute.getX(i), positionAttribute.getZ(i));
positionAttribute.setY(y + Math.cos(time * 0.4 + i * 0.01) * 0.3, positionAttribute.getY(i), positionAttribute.getZ(i));
}
galaxyParticles.geometry.attributes.position.needsUpdate = true;
// --- 2. Starfield Movement (Simulating camera movement/parallax) ---
starFieldParticles.rotation.y += 0.0001; // Very slow, ambient drift
// Tilt the view based on mouse position (Camera manipulation for interactive feel)
camera.position.x += (mouseX * 5 - camera.position.x) * 0.05;
camera.position.y += (mouseY * 5 - camera.position.y) * 0.05;
// Keep the camera constrained from flying too far away
camera.lookAt(scene.position);
// --- 3. Render the scene ---
renderer.render(scene, camera);
// Update FPS counter
updateFPS();
}
/**
* Updates and displays the Frames Per Second count.
*/
function updateFPS() {
frameCount++;
const currentTime = performance.now();
const elapsed = (currentTime - lastTime) / 1000; // Time in seconds
if (elapsed >= 1) {
const fps = Math.round(frameCount / elapsed);
fpsDisplay.textContent = `FPS: ${fps}`;
// Reset for next second calculation
frameCount = 0;
lastTime = currentTime;
}
}
/**
* Main function to run the animation.
*/
function main() {
init();
animate();
}
main();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive 3D particle galaxy animation with mouse interaction and a starfield background - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
font-family: 'Arial', sans-serif;
}
canvas {
display: block;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-size: 14px;
background-color: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
pointer-events: none;
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: white;
font-size: 24px;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.7);
pointer-events: none;
opacity: 0.8;
}
#fps-counter {
position: absolute;
bottom: 10px;
right: 10px;
color: white;
font-size: 14px;
background-color: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="title">3D Galaxy Particle Animation</div>
<div id="info">Move your mouse to tilt the galaxy | Click to toggle rotation</div>
<div id="fps-counter">FPS: 0</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let rotationSpeed = 0.001;
let isRotating = true;
let clock = new THREE.Clock();
let stats;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
document.addEventListener('click', toggleRotation);
window.addEventListener('resize', onWindowResize);
// Start animation
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleGeometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy particles with spiral pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral galaxy formation
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 50;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color variations for galaxy effect
const color = new THREE.Color();
const hue = (Math.random() * 0.3 + 0.5); // Blue to purple range
const saturation = 0.8;
const lightness = Math.random() * 0.5 + 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random particle sizes
sizes[i] = Math.random() * 2 + 0.5;
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particleGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const particleMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
}
// Mouse movement handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.0005;
mouseY = (event.clientY - windowHalfY) * 0.0005;
}
// Toggle rotation on click
function toggleRotation() {
isRotating = !isRotating;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Rotate particles
if (isRotating) {
particles.rotation.y += rotationSpeed;
}
// Mouse tilt effect
camera.position.x += (mouseX * 50 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 50 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// Update FPS counter
const fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${fps}`;
renderer.render(scene, camera);
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this 3D Galaxy Animation:
1. **Galaxy Visualization**:
- 5000 colorful particles forming a spiral galaxy pattern
- Blue to purple color scheme with additive blending for glow effect
- Particles with varying sizes and opacities
2. **Interactive Elements**:
- Mouse movement tilts the entire galaxy
- Click anywhere to toggle rotation on/off
- Smooth camera movement that follows mouse position
3. **Visual Enhancements**:
- Starfield background with 10,000 stars
- Additive blending for particle glow effect
- Responsive design that adapts to window size
- FPS counter in the bottom-right corner
4. **Performance Optimizations**:
- Uses BufferGeometry for efficient particle rendering
- WebGL renderer with antialiasing
- Smooth animation using requestAnimationFrame
The animation creates an immersive experience with a rotating galaxy that responds to mouse movements, creating a dynamic and visually appealing effect. The starfield background adds depth to the scene, making the galaxy appear in space.
gemma4:e4b
This solution provides a complete, self-contained HTML file that implements the requested interactive 3D particle animation using Three.js.
The galaxy spiral is created using `BufferGeometry` for high performance. The camera tilt responds smoothly to mouse movement, and an FPS counter tracks real-time performance.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Spiral Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
left: 20px;
padding: 8px 15px;
background: rgba(0, 0, 0, 0.6);
color: #ffffff;
font-family: 'Arial', sans-serif;
font-size: 16px;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: --</div>
<!-- Include Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starField;
let mouseX = 0, mouseY = 0;
// Animation variables for smoothness and timing
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
// FPS tracking variables
let frameCount = 0;
let lastTime = performance.now();
let fpsElement = document.getElementById('fps-counter');
/**
* Initialization function: Sets up the scene, camera, and particles.
*/
function init() {
// 1. Setup Scene, Camera, Renderer
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera.position.z = 50;
// 2. Create the Galaxy Spiral Particle System
createGalaxySpiral();
// 3. Create Starfield Background
createStarField(50000); // More stars for depth effect
// 4. Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Start the animation loop
animate();
}
/**
* Generates the main spiraling galaxy particle system.
*/
function createGalaxySpiral() {
const count = 5000;
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < count; i++) {
// Use the index 'i' to define position along a spiral path
const t = i / count * Math.PI * 6 + (Math.random() - 0.5) * 1; // Total rotation angle
// Spiral logic: Radius increases with distance/index, Z defines depth
let r = (i / count) * 200 + Math.random() * 5; // Max radius 200
let zPos = i * 0.1 - 300; // Deep into the scene
// Calculate coordinates in a spiral pattern
const x = r * Math.cos(t);
const y = (Math.random() - 0.5) * 20; // Small vertical spread
const z = zPos;
positions.push(x, y, z);
// Color variation based on depth/radius for a natural look
color.setHSL(i / count, 1, Math.random() * 0.5 + 0.3);
colors.push(color.r, color.g, color.b);
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Use PointsMaterial for efficiency and set point size
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors defined in the geometry
blending: THREE.AdditiveBlending, // Makes particles glow nicely
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Generates a massive starfield background (randomly placed points).
* @param {number} count - Number of stars to generate.
*/
function createStarField(count) {
const positions = [];
const colors = [];
for (let i = 0; i < count; i++) {
// Scatter stars randomly in a large cube area
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
positions.push(x, y, z);
// Give stars a faint white/blue color
colors.push(1 + Math.random() * 0.3, 1 + Math.random() * 0.3, 1 + Math.random() * 0.3);
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
blending: THREE.AdditiveBlending,
transparent: true,
opacity: 0.7
});
starField = new THREE.Points(geometry, material);
scene.add(starField);
}
/**
* Handles window resizing to keep the renderer and camera updated.
*/
function onWindowResize() {
camera.viewport.set(0, 0, 1, 1);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Captures mouse movement coordinates for interactivity.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100; // Scale down the effect
mouseY = (event.clientY - windowHalfY) / 100;
}
/**
* The main animation loop.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() * 0.0001; // Convert ms to seconds for sinusoidal movement
// --- Update Particles ---
// 1. Galaxy Spiral Rotation (Slow rotation over time)
galaxyParticles.rotation.y += 0.0005;
galaxyParticles.rotation.x = Math.sin(time * 0.2) * 0.1;
// 2. Starfield Movement (Subtle parallax shift)
starField.position.y += Math.sin(time * 0.3) * 0.01;
starField.rotation.z = time * 0.05;
// --- Update Camera Tilt based on Mouse Position (Interactivity) ---
// Smoothly interpolate camera rotation towards the mouse position
camera.rotation.x += (mouseY * 0.001 - camera.rotation.x) * 0.05;
camera.rotation.y += (mouseX * 0.001 - camera.rotation.y) * 0.05;
// --- Performance Tracking (FPS) ---
updateFPS();
renderer.render(scene, camera);
}
/**
* Calculates and displays the Frame Rate (FPS).
*/
function updateFPS() {
const currentTime = performance.now();
const elapsed = currentTime - lastTime;
frameCount++;
if (elapsed >= 1000) { // Update every 1 second
let fps = Math.round(frameCount * (1000 / elapsed));
fpsElement.textContent = `FPS: ${fps}`;
// Reset for the next calculation cycle
lastTime = currentTime;
frameCount = 0;
}
}
// --- Execution Start ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D particle animation with a galaxy-like spiral, responsive to mouse movement, and a starfield background - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
max-width: 300px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
font-size: 1rem;
line-height: 1.5;
margin-bottom: 15px;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#instructions {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 12px 20px;
border-radius: 30px;
text-align: center;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>This visualization features 5,000 colorful particles arranged in a galaxy-like spiral pattern.</p>
<p>Move your mouse to tilt the galaxy and explore its structure. The background includes a starfield for depth.</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to interact with the galaxy | <span class="highlight">Click & drag</span> to rotate view</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 15, 30);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 25;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add lighting
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(5, 5, 5);
scene.add(pointLight);
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 15;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 5;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color based on position and time
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) + (i / particleCount) * 0.2;
color.setHSL(hue, 1, 0.5);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random size
sizes[i] = Math.random() * 1.5 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 0.2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starCount = 10000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(starCount * 3);
const colors = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
// Position stars in a sphere around the galaxy
const radius = 50 + Math.random() * 100;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positions[i3 + 2] = radius * Math.cos(phi);
// Star colors (white to blue-white)
const color = new THREE.Color();
color.setHSL(0.65 + Math.random() * 0.1, 0.7, 0.8 + Math.random() * 0.2);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const starMaterial = new THREE.PointsMaterial({
size: 0.1,
vertexColors: true,
transparent: true,
opacity: 0.8
});
const starField = new THREE.Points(geometry, starMaterial);
scene.add(starField);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.01;
mouseY = (event.clientY - windowHalfY) * 0.01;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAn
gemma4:e4b
This is a comprehensive single-file implementation that uses Three.js to create the requested interactive 3D particle animation.
Due to the complexity and length of the required JavaScript (especially handling geometry generation, physics/interaction, and performance monitoring), the code is structured with detailed comments explaining each section.
### Full Code Implementation (Single HTML File)
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: monospace;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
user-select: none; /* Prevent text selection */
}
</style>
</head>
<body>
<!-- FPS Counter will be placed here -->
<div id="fpsCounter">FPS: 0</div>
<!-- Include Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// =========================
// GLOBAL VARIABLES & INITIALIZATION
// =========================
let scene, camera, renderer;
let galaxyParticles, starField;
const NUM_GALACTIC_PARTICLES = 5000;
const STARFIELD_SIZE = 1000;
// Mouse interaction tracking
let mouseX = 0;
let mouseY = 0;
// FPS Tracking variables
let frameCount = 0;
let lastTime = performance.now();
const fpsElement = document.getElementById('fpsCounter');
/**
* Initializes the Three.js environment (Scene, Camera, Renderer).
*/
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
// 2. Camera Setup (Perspective for depth perception)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 50;
// 3. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove);
// 5. Create Components
createGalaxyParticles();
createStarField();
// Start the animation loop
animate();
}
/**
* Generates the main spiral galaxy particle field.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Create particles in a spiral pattern (simulating rotational structure)
for (let i = 0; i < NUM_GALACTIC_PARTICLES; i++) {
// Calculate position based on index 'i' to create a spiral
const angle = (i / NUM_GALACTIC_PARTICLES) * Math.PI * 4 + (Math.random() - 0.5) * 1;
// Radius calculation: smaller radius for outer particles, larger near center
let r = Math.pow(Math.random(), 2) * 30; // Max radius of 30 units
r *= Math.exp(-i / NUM_GALACTIC_PARTICLES); // Exponential decay to form the spiral
// Use sinusoidal variation for depth and width
const x = r * Math.cos(angle + (Math.random() - 0.5) * 1);
const y = r * Math.sin(angle) * 0.5;
const z = r * Math.sin(angle + (Math.random() - 0.5) * 1) * 0.5;
positions.push(x, y, z);
// Assign random vibrant colors
color.setHSL(Math.random(), 0.8, Math.random());
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup for glowing points
const material = new THREE.PointsMaterial({
size: 0.15, // Particle size
vertexColors: true, // Use per-particle colors
transparent: true,
opacity: 0.8,
blending: THREE.AdditiveBlending // Makes particles glow when overlapping
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a dense background starfield using random points.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < STARFIELD_SIZE * STARFIELD_SIZE / 10; i++) {
// Positions are far away, simulating deep space
const x = (Math.random() - 0.5) * STARFIELD_SIZE * 2;
const y = (Math.random() - 0.5) * STARFIELD_SIZE * 2;
const z = (Math.random() - 0.5) * STARFIELD_SIZE * 2;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material setup for stars (dim white points)
const material = new THREE.PointsMaterial({
size: 0.1,
color: 0xAAAAFF,
blending: THREE.AdditiveBlending,
transparent: true
});
starField = new THREE.Points(geometry, material);
scene.add(starField);
}
/**
* Handles window resizing to keep the canvas full screen.
*/
function onWindowResize() {
camera.viewport = { x: 0, y: 0, width: 1, height: 1 };
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
/**
* Tracks mouse movement for interaction effects.
* Normalizes coordinates between -1 and 1.
*/
function onMouseMove(event) {
mouseX = (event.clientX / window.innerWidth) * 2 - 1; // Range -1 to 1
mouseY = -(event.clientY / window.innerHeight) * 2 - 1; // Range -1 to 1
}
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() * 0.001;
// =========================
// 1. INTERACTION & CAMERA UPDATE (Mouse Tilt)
// =========================
// Smoothly transition camera rotation based on mouse input
camera.rotation.x += (mouseY * 0.005 - camera.rotation.x) * 0.05;
camera.rotation.y += (mouseX * 0.005 - camera.rotation.y) * 0.05;
// =========================
// 2. GALAXY ANIMATION
// =========================
galaxyParticles.rotation.x += 0.0001; // Slow rotation on X axis
galaxyParticles.rotation.y += 0.0005; // Faster rotation on Y axis
// Make the entire galaxy slowly pulse/float (optional depth effect)
galaxyParticles.scale.set(1, 1, 1 + Math.sin(time * 0.2) * 0.02);
// =========================
// 3. STARFIELD ANIMATION
// =========================
// Make the starfield slowly drift/rotate around the camera
starField.rotation.y += 0.0001;
// =========================
// 4. RENDER & PERFORMANCE UPDATE
// =========================
renderer.render(scene, camera);
updateFPS();
}
/**
* Updates and displays the FPS counter in the corner.
*/
function updateFPS() {
const currentTime = performance.now();
const delta = currentTime - lastTime;
// Calculate FPS: (1000ms / time elapsed since last frame)
const fps = 1000 / (delta / frameCount);
fpsElement.textContent = `FPS: ${Math.round(fps)}`;
frameCount++;
if (currentTime - lastTime >= 1000) { // Update every second
// Reset counter and time tracking
lastTime = currentTime;
frameCount = 0;
}
}
// Start the application
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive 3D particle galaxy animation with mouse interaction and a starfield background - all in a single HTML file using Three.js.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
max-width: 300px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
font-size: 0.9rem;
line-height: 1.5;
margin-bottom: 15px;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
text-align: center;
font-size: 0.9rem;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Galaxy Particle Animation</h1>
<p>This interactive 3D visualization features:</p>
<ul>
<li>5,000 colorful particles in a galaxy spiral</li>
<li>Mouse tilt interaction for dynamic viewing</li>
<li>Starfield background with twinkling stars</li>
<li>Real-time FPS counter</li>
<li>Smooth animations and visual effects</li>
</ul>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Click and drag to rotate</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let starfield, starParticles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 50, 150);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 100;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy with spiral pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 50;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 10;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color based on position and rotation
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) % 1;
color.setHSL(hue, 0.8, 0.5);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starCount = 2000;
const starGeometry = new THREE.BufferGeometry();
const starPositions = new Float32Array(starCount * 3);
const starSizes = new Float32Array(starCount);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
// Random positions in a sphere
const radius = 100 + Math.random() * 200;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
starPositions[i3] = radius * Math.sin(phi) * Math.cos(theta);
starPositions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
starPositions[i3 + 2] = radius * Math.cos(phi);
// Random sizes
starSizes[i] = Math.random() * 1.5;
}
starGeometry.setAttribute('position', new THREE.BufferAttribute(starPositions, 3));
starGeometry.setAttribute('size', new THREE.BufferAttribute(starSizes, 1));
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true,
transparent: true,
opacity: 0.7
});
starfield = new THREE.Points(starGeometry, starMaterial);
scene.add(starfield);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Update controls
controls.update();
// Rotate galaxy particles
if
gemma4:e4b
This implementation uses advanced techniques in Three.js, including `BufferGeometry`, parametric coordinates for the spiral layout, and event handling for interactive camera movement, all within a single file structure for portability.
### 🌌 Galactic Spiral Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: fixed;
top: 10px;
left: 10px;
padding: 8px 12px;
background-color: rgba(0, 0, 0, 0.6);
color: #ffffff;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<!-- FPS counter will be displayed here -->
<div id="fps-counter">FPS: 0</div>
<!-- Load Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyGroup, starFieldGroup;
const NUM_GALAXIES = 5000;
const NUM_STARS = 10000;
let mouseX = 0;
let mouseY = 0;
// FPS Counter variables
let frameCount = 0;
let lastTime = performance.now();
/**
* Initializes the Three.js environment (Scene, Camera, Renderer)
*/
function init() {
// Scene setup
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x000011, 1, 500);
// Camera setup
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.set(0, 0, 50);
// Renderer setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// --- Create Components ---
createGalaxyParticles();
createStarField();
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove, false);
}
/**
* Generates the spiral galaxy particle system.
*/
function createGalaxyParticles() {
const particlesGeometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Parameters for the spiral shape
const maxRadius = 200;
const depthFactor = 350; // Controls how deep the spiral is in Z
for (let i = 0; i < NUM_GALAXIES; i++) {
// Parameter 't' controls the position along the spiral path
const t = Math.random() * Math.PI * 4;
// Use a modified Archimedean spiral equation: R = A * theta
// We modify it to create a galaxy-like depth curve
let x = maxRadius * (t / (Math.PI * 4)); // X grows with angle t
let y = Math.random() * 150 - 75; // Y is roughly centered and slightly varied
let z = depthFactor * (Math.cos(t) * 0.5); // Z gives the winding effect
// Add slight randomness to make it look natural
x += Math.random() * 30 - 15;
y += Math.random() * 20 - 10;
z *= (Math.random() * 0.8 + 0.2);
positions.push(x, y, z);
// Assign random colors for a colorful look
color.setHSL(i / NUM_GALAXIES, 1.0, Math.random());
colors.push(color.r, color.g, color.b);
}
particlesGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
particlesGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material for the particles (using vertex colors)
const particleMaterial = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.8
});
galaxyGroup = new THREE.Points(particlesGeometry, particleMaterial);
scene.add(galaxyGroup);
}
/**
* Generates a random starfield in the background.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < NUM_STARS; i++) {
// Stars are spread across a large cube volume
positions.push(
(Math.random() - 0.5) * 3000, // X: -1500 to 1500
(Math.random() - 0.5) * 3000, // Y
(Math.random() - 0.5) * 3000 // Z
);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
color: 0xaaaaaa, // Dim white/gray color
size: 1,
transparent: true,
opacity: 0.8
});
starFieldGroup = new THREE.Points(geometry, material);
scene.add(starFieldGroup);
}
/**
* Handles mouse movement and calculates rotation offset.
* @param {Event} event - The mouse move event.
*/
function onDocumentMouseMove(event) {
// Normalize coordinates to range between -1 and 1
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* Handles window resizing.
*/
function onWindowResize() {
camera.viewport.setSize(window.innerWidth, window.innerHeight);
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
// --- 1. Galaxy Animation (Rotation) ---
galaxyGroup.rotation.y += 0.0005; // Slow rotation around Y axis
galaxyGroup.rotation.x = Math.sin(performance.now() * 0.0001) * 0.05;
// --- 2. Starfield Animation (Subtle Movement) ---
starFieldGroup.rotation.y += 0.00001; // Very slow rotation for parallax effect
// --- 3. Interactivity (Mouse Tilt) ---
// Smoothly apply the mouse input to tilt the camera view
const targetRotationX = mouseY * 0.2;
const targetRotationY = mouseX * 0.2;
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.1;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.1;
// --- Render and FPS Update ---
renderer.render(scene, camera);
updateFPS();
}
/**
* Updates the visible frame rate counter.
*/
function updateFPS() {
const now = performance.now();
const delta = (now - lastTime) / 1000; // Time in seconds since last frame
frameCount++;
if (delta >= 0.5) { // Update FPS display roughly twice per second
const fps = Math.round(frameCount / delta);
document.getElementById('fps-counter').textContent = `FPS: ${fps}`;
// Reset counters and time for the next interval
frameCount = 0;
lastTime = now;
}
}
// --- Execution Start ---
init();
animate();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D galaxy animation with 5000 particles, mouse tilt response, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
font-family: 'Arial', sans-serif;
}
canvas {
display: block;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
pointer-events: none;
z-index: 100;
}
#title {
position: absolute;
top: 10px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.9);
font-size: 24px;
font-weight: bold;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.8);
pointer-events: none;
z-index: 100;
}
#instructions {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
pointer-events: none;
z-index: 100;
}
</style>
</head>
<body>
<div id="title">Interactive 3D Galaxy Animation</div>
<div id="info">Particles: 5000 | FPS: <span id="fps">0</span></div>
<div id="instructions">Move your mouse to tilt the galaxy | Click and drag to rotate</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 50, 200);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 150;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.2,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 50;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 10;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color based on position (blue to yellow)
const color = new THREE.Color();
const hue = (0.6 + Math.random() * 0.4) % 1;
const saturation = 0.7 + Math.random() * 0.3;
const lightness = 0.3 + Math.random() * 0.5;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 1.5 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate galaxy
particleSystem.rotation.y += 0.001;
particleSystem.rotation.x = mouseY * 0.2;
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
// Update FPS counter
const fps = Math.round(1 / delta);
document.getElementById('fps').textContent = fps;
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this Interactive Galaxy Animation:
1. **5000 Colorful Particles**: Created in a beautiful spiral galaxy pattern with varying colors and sizes
2. **Mouse Interaction**:
- Tilts the galaxy based on mouse position
- Click and drag to rotate the entire scene
3. **Starfield Background**: 10,000 stars scattered throughout space for depth
4. **FPS Counter**: Displays real-time frames per second in the top-left corner
5. **Smooth Animations**:
- Continuous galaxy rotation
- Smooth camera controls with damping
- Responsive design that adapts to window size
6. **Visual Effects**:
- Fog for depth perception
- Colorful particles with varying hues
- Semi-transparent particles for a glowing effect
The animation is contained in a single HTML file and uses Three.js from CDN for all 3D rendering capabilities. Simply open the file in any modern browser to experience the interactive galaxy!
gemma4:e4b
This comprehensive solution provides a visually stunning, interactive particle animation using Three.js within a single HTML file.
The animation features:
1. **Galaxy Spiral:** 5000 colorful particles arranged in a convincing spiral structure.
2. **Mouse Interaction:** The entire galaxy system tilts and rotates based on your mouse movement (parallax effect).
3. **Starfield Background:** A dense, twinkling star background adds depth.
4. **FPS Counter:** Real-time performance monitoring visible in the corner.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particle Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fps-counter {
position: fixed;
top: 20px;
left: 20px;
color: white;
font-family: 'Arial', sans-serif;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 8px;
z-index: 10;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: --</div>
<!-- Load Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- GLOBAL VARIABLES AND SETUP ---
let scene, camera, renderer;
let particlesGroup; // Group for the main galaxy system
let starFieldParticles; // For background stars
const PARTICLE_COUNT = 5000;
const MAX_STARS = 10000;
// Mouse tracking variables
let mouseX = 0;
let mouseY = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
// FPS tracking variables
let frameCount = 0;
let startTime = Date.now();
const fpsCounterElement = document.getElementById('fps-counter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// Scene Setup
scene = new THREE.Scene();
// Camera Setup (Perspective for depth)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 50;
// Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// --- CREATE OBJECTS ---
createGalaxyParticles();
createStarField();
// Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Start the animation loop
animate();
}
/**
* Generates the main galaxy spiral particle system.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < PARTICLE_COUNT; i++) {
// 1. Spiral Positioning Logic:
// Use polar coordinates mapped to a spiral curve (r = theta * k)
// Angle spread across the circle
const angle = Math.random() * Math.PI * 2;
// Distance from center (R): Exponential decay/increase for a galaxy look
let r = Math.pow(Math.random(), 0.8) * 15 + 5; // Ensures particles are spread out
// Length of the spiral arm: more distance means larger radius expansion
const armLengthFactor = (i / PARTICLE_COUNT) * 2;
r *= (1 + Math.sin(angle * 0.5) * 0.5); // Adds a wavy effect to the arms
// Calculate X, Y, Z based on polar coordinates
const x = r * Math.cos(angle - armLengthFactor);
const y = r * Math.sin(angle);
const z = r * Math.sin(angle * 0.5) + (Math.random() - 0.5) * 10; // Z depth variation
positions.push(x, y, z);
// 2. Random Coloring:
color.setHSL(Math.random(), 1, Math.random());
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup for colored particles
const material = new THREE.PointsMaterial({
size: 0.15,
vertexColors: true, // Use per-particle color attribute
transparent: true,
opacity: 0.9
});
particlesGroup = new THREE.Points(geometry, material);
scene.add(particlesGroup);
}
/**
* Creates a static starfield in the deep background.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < MAX_STARS; i++) {
// Spread stars across a vast cube (-2000 to 2000)
const x = Math.random() * 4000 - 2000;
const y = Math.random() * 4000 - 2000;
const z = Math.random() * 4000 - 2000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a simple material for the stars
const material = new THREE.PointsMaterial({
size: 1,
color: '#aaaaee',
transparent: true,
opacity: 0.7
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
// --- INTERACTION HANDLERS ---
/**
* Updates mouse coordinates and stores them for camera rotation.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 50; // Divisor controls sensitivity
mouseY = (event.clientY - windowHalfY) / 50;
}
/**
* Handles window resizing to keep the canvas filling the screen.
*/
function onWindowResize() {
camera.viewport.set(0, 0, 1, 1);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// --- ANIMATION LOOP AND LOGIC ---
/**
* Main animation loop function called every frame.
*/
function animate() {
requestAnimationFrame(animate);
const time = Date.now() * 0.0001;
// 1. Particle Movement (Subtle rotation/drift)
particlesGroup.rotation.x += 0.0005;
particlesGroup.rotation.y += 0.0008;
// 2. Interactivity: Tilt the entire scene based on mouse position
const targetRotationX = -mouseY * 0.001;
const targetRotationY = mouseX * 0.001;
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.05;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.05;
// 3. Rendering
renderer.render(scene, camera);
// 4. FPS Calculation and Display
frameCount++;
const elapsed = Date.now() - startTime;
if (elapsed >= 1000) {
const fps = Math.round((frameCount / elapsed) * 1000);
fpsCounterElement.textContent = `FPS: ${fps}`;
// Reset timer and counter for next calculation
startTime = Date.now();
frameCount = 0;
}
}
// Start the application
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an interactive 3D particle galaxy animation with mouse tilt response, starfield background, and FPS counter - all in a single HTML file using Three.js.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
cursor: move;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.8);
font-size: 24px;
font-weight: bold;
z-index: 100;
text-shadow: 0 0 10px rgba(0, 150, 255, 0.7);
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
backdrop-filter: blur(5px);
}
</style>
</head>
<body>
<div id="container">
<div id="title">3D GALAXY PARTICLE ANIMATION</div>
<div id="info">Interactive Particle Galaxy | 5000 Particles | Mouse Tilt Control</div>
<div id="fps-counter">FPS: 60</div>
<div id="instructions">Move mouse to tilt the galaxy | Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 60, lastFpsUpdate: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 500, 1500);
// Create camera
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
3000
);
camera.position.z = 1000;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.addEventListener('wheel', onMouseWheel);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy with spiral structure
for (let i = 0; i < particleCount; i++) {
const radius = Math.random() * 500;
const angle = Math.random() * Math.PI * 2;
// Spiral arms
const spiralAngle = angle + Math.sin(radius / 100) * 0.5;
const x = Math.cos(spiralAngle) * radius;
const y = Math.sin(spiralAngle) * radius;
const z = (Math.random() - 0.5) * 50;
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
// Color based on position
const color = new THREE.Color();
const hue = (radius / 500) * 0.2 + Math.random() * 0.1;
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
// Size variation
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Mouse move event handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.0005;
mouseY = (event.clientY - windowHalfY) * 0.0005;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Mouse wheel zoom handler
function onMouseWheel(event) {
camera.position.z += event.deltaY * 0.01;
camera.position.z = Math.min(Math.max(camera.position.z, 300), 2000);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Update particle rotation based on mouse position
if (particleSystem) {
particleSystem.rotation.x = mouseY * 0.2;
particleSystem.rotation.y = mouseX * 0.2;
// Slowly rotate the galaxy
particleSystem.rotation.z += 0.0005;
}
// Update camera position based on mouse
if (controls) {
controls.update();
}
// Update FPS counter
updateFPS(delta);
renderer.render(scene, camera);
}
// Update FPS counter
function updateFPS(delta) {
stats.fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${stats.fps}`;
}
// Initialize the scene when the page loads
window.onload = init;
</script>
</body>
</html>
```
## Features of this 3D Galaxy Animation:
1. **Interactive Particle Galaxy**:
gemma4:e4b
This solution provides a complete, single HTML file that implements the requested interactive 3D particle animation using Three.js.
The galaxy particles are placed in a spiral pattern, respond dynamically to mouse movement (tilting the view), include a separate starfield background, and display a real-time FPS counter for performance monitoring.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.6);
color: white;
padding: 8px 15px;
border-radius: 5px;
font-family: 'Arial', sans-serif;
font-size: 14px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<!-- Include Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
const particleCount = 5000;
let mouseX = 0;
let mouseY = 0;
let originalCameraRotationY = 0;
// FPS Tracking Variables
let frameCount = 0;
let lastTime = performance.now();
const fpsDisplay = document.getElementById('fpsCounter');
/**
* Initialization function: Sets up the scene, camera, and objects.
*/
function init() {
// Scene setup
scene = new THREE.Scene();
// Camera setup (Perspective)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 50;
// Renderer setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// --- Create Objects ---
createGalaxyParticles();
createStarfieldBackground();
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove, false);
// Start the animation loop
animate();
}
/**
* Generates the main galaxy particle system in a spiral pattern.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Color and Size definition
const color = new THREE.Color();
for (let i = 0; i < particleCount; i++) {
// Calculate position based on index (i) to simulate a spiral/disk shape
const t = (i / particleCount) * Math.PI * 4; // Controls the rotation/spread factor
// Spiral formula approximation: Radius increases with angle, Z is depth
const r = Math.sin(t) * 50 + 20; // Varies radius between 30 and 70
const z = (i - particleCount / 2) / (particleCount / 2) * 10; // Spread particles along Z-axis
// X coordinate: r * cos(t)
positions.push(r * Math.cos(t));
// Y coordinate: sin(t) * random variation
positions.push(Math.sin(t) * (i % 10 === 0 ? 5 : 1) + Math.random() * 2);
// Z coordinate: z
positions.push(z);
// Assign random bright colors for a galaxy feel
color.setHSL((i / particleCount), 0.8, Math.random() * 0.5 + 0.5);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup: Use PointsMaterial for performance
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Allows using the color attribute from geometry
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Generates a static starfield background far away from the main galaxy.
*/
function createStarfieldBackground() {
const geometry = new THREE.BufferGeometry();
const positions = [];
// Create 50,000 random stars in a large sphere
for (let i = 0; i < 50000; i++) {
// Random coordinates within a large sphere radius of 1000
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a smaller point size and slightly different material for contrast
const material = new THREE.PointsMaterial({
size: 1.5,
color: 0xaaaaff, // Soft blue/white color
transparent: true,
opacity: 0.7
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
/**
* Handles resizing the canvas when the window size changes.
*/
function onWindowResize() {
camera.viewport = { x: 0, y: 0, width: 1, height: 1 };
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Handles mouse movement and updates the camera/objects accordingly.
* @param {MouseEvent} event - The mouse movement event.
*/
function onDocumentMouseMove(event) {
// Normalize coordinates to range [-1, 1]
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now();
const delta = (time - lastTime) / 1000; // Time elapsed since last frame in seconds
// --- Performance Tracking ---
frameCount++;
if (time > lastTime + 1000) {
const fps = Math.round(frameCount / ((time - lastTime) / 1000));
fpsDisplay.textContent = `FPS: ${fps}`;
frameCount = 0;
lastTime = time;
}
// --- Animation Logic ---
// 1. Galaxy Rotation (Slow, constant rotation)
galaxyParticles.rotation.x += delta * 0.05;
galaxyParticles.rotation.y += delta * 0.03;
// 2. Starfield Parallax/Rotation (Subtle movement to enhance depth)
starfieldParticles.rotation.z += delta * 0.01;
starfieldParticles.position.x = Math.sin(time / 5000) * 50;
// 3. Camera Tilt/LookAt (Responsive to mouse input)
// Smoothly interpolate the camera's target rotation based on mouse position
const targetRotationX = mouseY * 0.1;
const targetRotationY = mouseX * 0.1;
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.05;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.05;
// Render the scene
renderer.render(scene, camera);
}
// Start everything once the script loads
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an interactive 3D particle galaxy animation with mouse tilt response and a starfield background using Three.js. Here's the complete solution:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
max-width: 300px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7e5f, #feb47b);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 126, 95, 0.3);
}
#info p {
margin-bottom: 10px;
font-size: 0.9rem;
line-height: 1.5;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
text-align: center;
font-size: 0.9rem;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.highlight {
color: #ff7e5f;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>3D Galaxy Particle Animation</h1>
<p>This interactive visualization shows 5000 colorful particles forming a galaxy-like spiral.</p>
<p>Move your mouse to <span class="highlight">tilt the galaxy</span> and explore the cosmic scene.</p>
<p>Particles rotate in a spiral pattern with varying speeds and colors for a realistic effect.</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move mouse to tilt | Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Add orbit controls for manual interaction
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (Math.random() * 0.4 + 0.5); // Blue to purple range
const saturation = 0.8;
const lightness = Math.random() * 0.5 + 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create particle material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Rotate particles
if (particles) {
particles.rotation.x += 0.0005;
particles.rotation.y += 0.001;
// Mouse tilt effect
camera.position.x += (mouseX * 50 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 50 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update FPS counter
const fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${fps}`;
renderer.render(scene, camera);
}
// Initialize the scene when the page loads
window.onload = init;
</script>
</body>
</html>
```
## Features of this Interactive Galaxy Animation:
1. **5000 Colorful Particles**: Created in a spiral galaxy pattern with varying colors and sizes
2. **Mouse Interaction**: Tilts the galaxy
gemma4:e4b
This is a complex task requiring advanced JavaScript physics/graphics programming (Three.js). Since I cannot run live server code or external file dependencies, I will provide a complete, single-file HTML solution that you can save and open in a modern browser to see the full interactive effect.
### 🌌 Cosmic Particle Galaxy Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 10px;
right: 10px;
color: #ffffff;
font-family: 'Arial', sans-serif;
font-size: 16px;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 8px;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 60</div>
<!-- Include Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starParticles;
const NUM_GALAXY = 5000;
const NUM_STARS = 30000;
// Mouse tracking for interactivity
let mouseX = 0;
let mouseY = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
// FPS Tracking variables
let frameCount = 0;
let lastTime = performance.now();
let fpsElement = document.getElementById('fpsCounter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000033, 0.005); // Deep space fog
// 2. Camera Setup (Perspective)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 10, 100);
camera.lookAt(0, 0, 0);
// 3. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Create Particle Systems
createGalaxy();
createStars();
// Start the animation loop
animate();
}
/**
* Creates the main galaxy particle system (spiral shape).
*/
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Generate particles in a spiral pattern
for (let i = 0; i < NUM_GALAXY; i++) {
// Calculate position using polar coordinates for a spiral shape
const angle = Math.random() * Math.PI * 2;
const radiusFactor = Math.sqrt(Math.random()); // Weighting density towards center
// Galaxy structure: larger radii closer to the "arms"
let r = (radiusFactor + 0.5) * (1 + Math.sin(i / NUM_GALAXY * Math.PI * 3) * 0.5);
// Add slight z-axis depth variation for a 3D structure
const z = (Math.random() - 0.5) * 2;
positions.push(r * Math.cos(angle), r * Math.sin(angle), z * 10);
// Give particles random, vibrant colors
color.setHSL(Math.random(), Math.random() * 0.8 + 0.2, Math.random());
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Particle Material (using vertex colors)
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true, // Enable using the color attribute
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a dense, random starfield background particle system.
*/
function createStars() {
const geometry = new THREE.BufferGeometry();
const positions = [];
// Distribute stars in a large cube volume
for (let i = 0; i < NUM_STARS; i++) {
// Stars are spread out over a large area (-500 to 500)
positions.push(
(Math.random() - 0.5) * 1000,
(Math.random() - 0.5) * 1000,
(Math.random() - 0.5) * 1000
);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material for stars: small, white, and non-glowing
const material = new THREE.PointsMaterial({
size: 1.5,
color: 0xaaaaee,
transparent: true,
blending: THREE.AdditiveBlending // Makes stars glow when overlapping
});
starParticles = new THREE.Points(geometry, material);
scene.add(starParticles);
}
/**
* Handles mouse movement and updates the global coordinates.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100; // Scaling factor for sensitivity
mouseY = (event.clientY - windowHalfY) / 100;
}
/**
* Handles window resizing to keep the canvas fullscreen.
*/
function onWindowResize() {
camera.viewport = { x: 0, y: 0, width: 1, height: 1 };
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* The main animation loop. Updates positions and renders the scene.
* @param {number} time - Current timestamp (unused but standard in requestAnimationFrame).
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() * 0.001;
// --- 1. Particle Updates ---
// Galaxy Rotation: Rotate the entire galaxy slowly
galaxyParticles.rotation.y += 0.001;
galaxyParticles.rotation.x = Math.sin(time / 200) * 0.1; // Subtle breathing motion
// Starfield Movement: Simulate distant stars moving towards us (parallax effect)
starParticles.rotation.y += 0.0005;
// --- 2. Camera/Interactivity Updates ---
// Smoothly interpolate camera position and rotation based on mouse input
const targetX = mouseX * 0.1;
const targetY = mouseY * 0.1;
camera.position.x += (targetX - camera.position.x) * 0.05;
camera.position.y += ((windowHalfY - event ? event.clientY : window.innerHeight / 2) / window.innerWidth - camera.position.y) * 0.05;
// Apply rotation based on mouse input for tilt effect
const targetRotationX = mouseY * 0.01;
const targetRotationY = mouseX * 0.01;
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.05;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.05;
// --- 3. Rendering and FPS Update ---
renderer.render(scene, camera);
updateFPS();
}
/**
* Updates and displays the Frames Per Second counter.
*/
function updateFPS() {
const currentTime = performance.now();
const elapsed = currentTime - lastTime;
// Calculate FPS (Frames / Time)
const fps = 1000 / ((elapsed / frameCount));
fpsElement.textContent = `FPS: ${Math.round(fps)}`;
frameCount++;
lastTime = currentTime;
// Reset counter every second to prevent overflow
if (elapsed >= 1000) {
frameCount = 0;
lastTime = performance.now();
}
}
// --- Execution Start ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D galaxy animation with 5000 particles, mouse interaction, and a starfield background - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
max-width: 300px;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #4facfe, #00f2fe);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(79, 172, 254, 0.5);
}
#info p {
font-size: 1rem;
line-height: 1.5;
margin-bottom: 15px;
}
#controls {
display: flex;
gap: 10px;
margin-top: 10px;
}
#controls button {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.3);
color: white;
padding: 8px 15px;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
#controls button:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateY(-2px);
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
backdrop-filter: blur(5px);
}
#loading {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: #000;
z-index: 200;
transition: opacity 1s ease;
}
.spinner {
width: 50px;
height: 50px;
border: 5px solid rgba(255, 255, 255, 0.1);
border-top: 5px solid #4facfe;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
#loading-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 1.2rem;
text-align: center;
}
.highlight {
color: #4facfe;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>This simulation features:</p>
<ul>
<li>5000 colorful particles in a galaxy spiral</li>
<li>Mouse interaction for rotation and tilt</li>
<li>Starfield background with depth effect</li>
<li>FPS counter in the corner</li>
<li>Smooth animations and transitions</li>
</ul>
<div id="controls">
<button id="reset">Reset View</button>
<button id="speed">Speed Up</button>
</div>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="loading">
<div class="spinner"></div>
<div id="loading-text">Loading Galaxy...</div>
</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0 };
let rotationSpeed = 0.001;
let particleCount = 5000;
let stars = [];
let starField;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 50, 200);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarField();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.getElementById('reset').addEventListener('click', resetView);
document.getElementById('speed').addEventListener('click', toggleSpeed);
// Hide loading screen
setTimeout(() => {
document.getElementById('loading').style.opacity = '0';
setTimeout(() => {
document.getElementById('loading').style.display = 'none';
}, 1000);
}, 1500);
// Start animation loop
animate();
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position particles in a spiral pattern
const radius = Math.sqrt(Math.random()) * 30;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 10;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (Math.random() * 0.4 + 0.5); // Blue to purple range
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.3 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random particle sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarField() {
const starGeometry = new THREE.BufferGeometry();
const starPositions = [];
const starSizes = [];
// Create 10,000 stars
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starPositions.push(x, y, z);
starSizes.push(Math.random() * 1.5 + 0.5);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
starGeometry.setAttribute('size', new THREE.Float
gemma4:e4b
This is a complex and visually intensive request that requires robust use of Three.js, trigonometry, and performance management (like FPS counting).
Here is the complete, single HTML file solution. Due to its complexity, I've added extensive comments explaining each section of the code.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Galaxy Particle Animation</title>
<style>
/* CSS for full screen canvas and overlay */
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fps-counter {
position: fixed;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.5);
color: #ffffff;
padding: 10px 20px;
border-radius: 8px;
font-family: monospace;
z-index: 100;
}
</style>
</head>
<body>
<!-- FPS Counter Overlay -->
<div id="fps-counter">FPS: --</div>
<!-- Three.js Library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starField;
// Performance tracking variables
let frameCount = 0;
let lastTime = performance.now();
const fpsElement = document.getElementById('fps-counter');
// Constants for particle generation
const NUM_GALACTIC_PARTICLES = 5000;
const STARFIELD_COUNT = 10000;
// --- Initialization Function ---
function init() {
// 1. SCENE SETUP
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 200);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set camera position slightly back to view the galaxy
camera.position.z = 50;
// 2. CREATE PARTICLES
createGalaxyParticles();
createStarField();
// 3. EVENT LISTENERS
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove, false);
// Start the animation loop
animate();
}
/**
* Creates the main galactic spiral particle system.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Spiral parameters (determines the shape)
const totalAngle = Math.PI * 6; // Full spiral rotation
const spiralArms = 3;
const armSpacing = totalAngle / spiralArms;
for (let i = 0; i < NUM_GALACTIC_PARTICLES; i++) {
// Calculate the angle for this particle, distributed across the spiral arms
let currentAngle = (i / NUM_GALACTIC_PARTICLES) * totalAngle;
let armIndex = Math.floor(i / (NUM_GALACTIC_PARTICLES / spiralArms));
// Distribute particles within an arm segment, then add the offset for the next arm
currentAngle += armIndex * armSpacing + (Math.random() - 0.5) * 0.1;
// Spiral Math: Radius increases with angle, creating the spiral effect
let radius = Math.pow(i / NUM_GALACTIC_PARTICLES, 0.8) * 30 + Math.random() * 5;
// Add subtle variation to make it look more natural (Gaussian noise approximation)
radius *= (1 + Math.sin(currentAngle * 2) * 0.1);
// Cartesian coordinates: x = r*cos(theta), y = r*sin(theta) (assuming a flat plane for simplicity, z variation added later)
let x = radius * Math.cos(currentAngle + armIndex * Math.PI / 3);
let y = radius * Math.sin(currentAngle + armIndex * Math.PI / 3) * 0.5; // Flattened Y axis for a disc look
let z = (Math.random() - 0.5) * 10; // Small random depth variation
positions.push(x, y, z);
// Random color generation (giving a colorful galaxy effect)
color.setHSL((i / NUM_GALACTIC_PARTICLES + Math.random() * 0.2), 1, 0.5 + Math.random() * 0.3);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup
const material = new THREE.PointsMaterial({
size: 0.5, // Size of the particles
vertexColors: true, // Use per-particle colors
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a dense, random starfield background.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < STARFIELD_COUNT; i++) {
// Place stars far away and randomly in a large cube volume
const x = (Math.random() - 0.5) * 400;
const y = (Math.random() - 0.5) * 400;
const z = (Math.random() - 0.5) * 400;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Star material: small white dots
const material = new THREE.PointsMaterial({
size: 1.5,
color: 0xaaaaee,
transparent: true,
opacity: 0.7
});
starField = new THREE.Points(geometry, material);
scene.add(starField);
}
// --- Interaction Handlers ---
/**
* Handles window resizing to maintain aspect ratio.
*/
function onWindowResize() {
camera.viewport.setSize(window.innerWidth, window.innerHeight);
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates the scene rotation based on mouse movement (tilt effect).
* @param {MouseEvent} event - The mouse event object.
*/
function onMouseMove(event) {
// Normalize mouse coordinates (-1 to +1 range)
const normalizedX = (event.clientX / window.innerWidth) * 2 - 1;
const normalizedY = -(event.clientY / window.innerHeight) * 2 + 1;
// Apply a small rotational change based on mouse movement
// This tilt effect makes the camera/scene respond to the user's position.
scene.rotation.y = normalizedX * 0.5; // Tilt horizontally
camera.rotation.x = normalizedY * 0.2; // Tilt vertically (less pronounced)
}
// --- Animation Loop and Updates ---
/**
* Main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now();
const delta = time - lastTime;
if (delta > 0) {
updateGalaxyParticles(delta / 1000); // Pass elapsed time in seconds
updateStarField(delta / 1000);
}
renderer.render(scene, camera);
// FPS Calculation
frameCount++;
const elapsed = Math.min(time - lastTime, 1000); // Cap the time measurement
if (elapsed >= 500) { // Update display every half second for stable reading
const fps = Math.round(frameCount * 1000 / elapsed);
fpsElement.textContent = `FPS: ${Math.max(1, fps)}`;
// Reset counters
frameCount = 0;
lastTime = time;
}
}
/**
* Updates the position of the galaxy particles for rotation and subtle movement.
* @param {number} delta - Time elapsed since last frame (in seconds).
*/
function updateGalaxyParticles(delta) {
const positions = galaxyParticles.geometry.attributes.position.array;
const speedFactor = 0.1 * delta;
for (let i = 0; i < NUM_GALACTIC_PARTICLES; i++) {
// Calculate the index for the x, y, z coordinates
let i3 = i * 3;
// Rotate around Y axis (Galaxy rotation)
positions[i3] += Math.sin(i * 0.1 + performance.now() / 5000) * speedFactor * 0.1;
positions[i3 + 2] -= Math.cos(i * 0.1 + performance.now() / 5000) * speedFactor * 0.1;
// Rotate around Z axis (Twisting effect)
let currentZ = positions[i3 + 2];
positions[i3] -= Math.sin(currentZ * 0.05 + performance.now() / 8000) * speedFactor * 0.1;
positions[i3 + 1] += Math.cos(currentZ * 0.05 + performance.now() / 8000) * speedFactor * 0.1;
}
// Mark the geometry as needing updates
galaxyParticles.geometry.attributes.position.needsUpdate = true;
}
/**
* Updates the position of the starfield particles to simulate movement/parallax.
* @param {number} delta - Time elapsed since last frame (in seconds).
*/
function updateStarField(delta) {
const positions = starField.geometry.attributes.position.array;
// Simulate slight camera drift or gentle background flow
for (let i = 0; i < STARFIELD_
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy simulation with 5000 colorful particles that respond to mouse movement, a starfield background, and an FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
z-index: 10;
max-width: 300px;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff758c);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 126, 179, 0.3);
}
#info p {
font-size: 1rem;
margin-bottom: 15px;
line-height: 1.5;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
font-family: monospace;
font-size: 1.2rem;
z-index: 10;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 30px;
backdrop-filter: blur(5px);
text-align: center;
font-size: 1rem;
z-index: 10;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>3D Galaxy Simulation</h1>
<p>This interactive visualization shows 5000 colorful particles rotating in a galaxy-like spiral.</p>
<p>Move your mouse to tilt the galaxy and explore the cosmic environment.</p>
<p>Experience the beauty of particle physics in real-time!</p>
</div>
<div id="fps-counter">FPS: 60</div>
<div id="instructions">Move your mouse to interact with the galaxy</div>
</div>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats = { fps: 60, lastFpsUpdate: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add stars background
createStarfield();
// Create particles
createParticles();
// Add orbit controls for mouse interaction
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createParticles() {
const particleGeometry = new THREE.BufferGeometry();
const particleMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy spiral pattern
for (let i = 0; i < particleCount; i++) {
const radius = Math.sqrt(Math.random()) * 150;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 40;
// Position
positions[i * 3] = Math.cos(angle) * radius;
positions[i * 3 + 1] = height;
positions[i * 3 + 2] = Math.sin(angle) * radius;
// Color - create galaxy colors (blues, purples, yellows)
const color = new THREE.Color();
const hue = Math.random() * 0.4 + 0.5; // Blue to purple range
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.3 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
// Size variation
sizes[i] = Math.random() * 3 + 0.5;
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particleGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate particles
if (particles) {
particles.rotation.x = elapsed * 0.05;
particles.rotation.y = elapsed * 0.02;
// Mouse interaction
camera.position.x += (mouseX * 5 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 5 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update FPS counter
updateFPSCounter();
// Render scene
renderer.render(scene, camera);
}
// Update FPS counter
function updateFPSCounter() {
const now = performance.now();
if (now >= stats.lastFpsUpdate + 1000) {
stats.fps = Math.round(1000 / (now - stats.lastFpsUpdate));
document.getElementById('fps-counter').textContent = `FPS: ${stats.fps}`;
stats.lastFpsUpdate = now;
}
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this Galaxy Animation:
gemma4:e4b
This implementation uses Three.js's `BufferGeometry` and `PointsMaterial` for high performance when rendering thousands of particles, creating a highly optimized galaxy effect with interactive controls.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: 'Consolas', monospace;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<!-- Three.js Library CDN -->
<script src="https://cdn.jsdelivr.net/npm/three@r128/build/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let particles, geometry, material;
const PARTICLE_COUNT = 5000;
let mouseX = 0;
let mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
// --- FPS Counter Variables ---
let frameCount = 0;
let lastTime = performance.now();
const fpsDisplay = document.getElementById('fpsCounter');
// --- Initialization Function ---
function init() {
// 1. Setup Scene, Camera, Renderer
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set initial camera position
camera.position.z = 50;
// 2. Create Particle System (The Galaxy)
generateParticles();
// 3. Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
}
/**
* Generates the spiral particle system geometry and material.
*/
function generateParticles() {
geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Parameters for the spiral shape (adjust these to change the galaxy look)
const maxRadius = 100;
const depthLength = 150;
for (let i = 0; i < PARTICLE_COUNT; i++) {
// Calculate angle and radius based on index 'i' for a spiral pattern
const theta = (i / PARTICLE_COUNT) * Math.PI * 6; // Full rotation multiple times
const r = Math.random() * maxRadius * (1 - Math.abs(Math.sin(theta)) * 0.5); // Variable radius
// Position coordinates (Spiral pattern: x=r*cos, y=r*sin, z=depth)
const x = r * Math.cos(theta);
const y = r * Math.sin(theta) * 0.8; // Slightly compress Y axis
const z = (i / PARTICLE_COUNT - 0.5) * depthLength; // Spread along Z-axis
positions.push(x, y, z);
// Color calculation: Vary color based on position/angle for a gradient effect
color.setHSL(i / PARTICLE_COUNT, 1.0, 0.6);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Particle Material (Using PointsMaterial for efficiency)
material = new THREE.PointsMaterial({
size: 0.8, // Size of the particles
vertexColors: true, // Use per-particle colors
blending: THREE.AdditiveBlending, // Makes them glow when overlapping
transparent: true
});
// Create the final Points object
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
/**
* Handles window resizing to keep the rendering correct.
*/
function onWindowResize() {
camera.viewport = null; // Reset viewport
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Handles mouse movement to control the camera view (tilt effect).
*/
function onDocumentMouseMove(event) {
// Normalize coordinates (-1 to +1 range)
mouseX = (event.clientX - windowHalfX) * 0.5;
mouseY = (event.clientY - windowHalfY) * 0.5;
}
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
// --- Animation Logic ---
// 1. Update Particle Rotation (Galaxy Spin)
particles.rotation.y += 0.001; // Slow rotation around Y axis
particles.rotation.z += 0.0005; // Slight tilt on Z axis
// 2. Camera/Scene Tilt Response to Mouse Input
// Smoothly interpolate the camera's target rotation based on mouse position
camera.lookAt(new THREE.Vector3(0, 0, -1));
camera.rotation.y += (mouseX * 0.005 - camera.rotation.y) * 0.05;
camera.rotation.x += (-mouseY * 0.005 - camera.rotation.x) * 0.05;
// --- FPS Calculation ---
const currentTime = performance.now();
const delta = currentTime - lastTime;
frameCount++;
if (delta >= 1000) { // Calculate FPS every second
const fps = Math.round(frameCount * 1000 / delta);
fpsDisplay.textContent = `FPS: ${fps}`;
// Reset counter and time base
frameCount = 0;
lastTime = currentTime;
}
// 3. Render Scene
renderer.render(scene, camera);
}
// --- Execution ---
init();
animate();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy simulation with 5000 particles that respond to mouse movement and include a starfield background. Here's the complete solution:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
cursor: pointer;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.9);
font-size: 28px;
font-weight: bold;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
letter-spacing: 2px;
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.8);
font-size: 16px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 8px 12px;
border-radius: 8px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
</style>
</head>
<body>
<div id="container">
<div id="title">INTERACTIVE GALAXY SIMULATION</div>
<div id="info">5,000 Particles | Galaxy Spiral | Mouse Interaction</div>
<div id="fps-counter">FPS: 60</div>
<div id="instructions">Move mouse to tilt galaxy | Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 60 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
2000
);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setAnimationLoop(animate);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.addEventListener('wheel', onMouseWheel);
}
// Create the galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 4;
const height = (Math.random() - 0.5) * 100;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color variations
const color = new THREE.Color();
const hue = (Math.random() * 0.5 + 0.5) % 1; // Blue to purple range
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Particle sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create particle material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starCount = 10000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(starCount * 3);
const colors = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
// Random positions in a sphere
const radius = 1000 + Math.random() * 5000;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positions[i3 + 2] = radius * Math.cos(phi);
// Star colors (white to blue-white)
const color = new THREE.Color();
const hue = Math.random() * 0.1; // Blue range
const saturation = 0.5 + Math.random() * 0.5;
const lightness = 0.8 + Math.random() * 0.2;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const starMaterial = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.8
});
const starfield = new THREE.Points(geometry, starMaterial);
scene.add(starfield);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.01;
mouseY = (event.clientY - windowHalfY) * 0.01;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Mouse wheel zoom
function onMouseWheel(event) {
camera.position.z += event.deltaY * 0.01;
camera.position.z = Math.min(Math.max(camera.position.z, 200), 1000);
}
// Animation loop
function animate() {
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate galaxy particles
if (particleSystem) {
particleSystem.rotation.y += 0.001;
particle
gemma4:e4b
This is a complex request that requires integrating multiple advanced JavaScript concepts (Three.js, event handling, game loops, performance monitoring) into a single file.
Here is the complete code for an interactive 3D particle galaxy animation.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fps-counter {
position: fixed;
top: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-family: 'Courier New', monospace;
background: rgba(0, 0, 0, 0.4);
padding: 10px 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// =============================
// GLOBAL VARIABLES & SETUP
// =============================
let scene, camera, renderer;
let particlesMesh, starfieldParticles;
const particleCount = 5000;
let mouseX = 0;
let mouseY = 0;
// FPS Counter variables
let frameCount = 0;
let lastTime = performance.now();
const fpsDiv = document.getElementById('fps-counter');
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011); // Deep space blue/black
// 2. Camera Setup (Perspective)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 3. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. Initialize Elements
createParticles();
createStarfield();
// 5. Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Start the animation loop
animate();
}
// =============================
// PARTICLE CREATION FUNCTIONS
// =============================
/**
* Creates the main galaxy spiral particle system.
*/
function createParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < particleCount; i++) {
// Index 'i' determines the position in the spiral structure
const normalizedIndex = i / particleCount;
// --- GALAXY SPIRAL LOGIC ---
// The radius R increases as the particle moves along the "spiral" path (normalized index)
// We use a function that grows slower than linear to create the spiral curve.
const r = 10 + Math.pow(normalizedIndex, 2) * 35;
// Angle increases steadily for the wrap-around effect
const theta = normalizedIndex * Math.PI * 6; // Total rotation angle (e.g., 6 full turns)
// Z depth varies to give thickness to the galaxy
const z = (Math.random() - 0.5) * 10;
// X and Y positions using polar coordinates: x = r*cos(theta), y = r*sin(theta)
positions.push(r * Math.cos(theta), r * Math.sin(theta), z);
// --- COLORING & RANDOMNESS ---
// Assign a colorful, slightly random hue to each particle
color.setHSL((normalizedIndex / particleCount * 0.5 + Math.random() * 0.1) % 1, 1.0, 0.7);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the color attribute defined in geometry
transparent: true,
opacity: 0.8
});
particlesMesh = new THREE.Points(geometry, material);
scene.add(particlesMesh);
}
/**
* Creates a dense, static starfield background.
*/
function createStarfield() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const count = 10000; // More stars for better density
for (let i = 0; i < count; i++) {
// Spread stars randomly far away from the origin
positions.push(
(Math.random() - 0.5) * 2000,
(Math.random() - 0.5) * 2000,
(Math.random() - 0.5) * 2000
);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a simple material for the stars
const material = new THREE.PointsMaterial({
size: 1.5,
color: 0xaaaaee, // Light blue/white color
transparent: true,
opacity: 0.7
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
// =============================
// EVENT HANDLERS & CONTROLS
// =============================
/**
* Updates mouse coordinates for camera interaction.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX / window.innerWidth - 0.5) * 2; // Normalized range [-1, 1]
mouseY = -(event.clientY / window.innerHeight - 0.5) * 2; // Normalized range [-1, 1]
}
/**
* Handles screen resizing to keep the canvas full size.
*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// =============================
// ANIMATION LOOP & LOGIC
// =============================
/**
* Updates the particle positions based on time and mouse input.
*/
function updateParticles() {
const clockTime = performance.now() * 0.001;
const positionAttribute = particlesMesh.geometry.attributes.position;
const positions = positionAttribute.array;
// Rotate the entire galaxy structure smoothly over time
const rotationSpeed = 0.0005;
const timeOffset = clockTime * rotationSpeed;
for (let i = 0; i < particleCount; i++) {
// Get current position for index 'i'
let x = positions[i * 3];
let y = positions[i * 3 + 1];
let z = positions[i * 3 + 2];
// Apply rotation around Z-axis (Galaxy spin)
const newX = x * Math.cos(timeOffset) - y * Math.sin(timeOffset);
const newY = x * Math.sin(timeOffset) + y * Math.cos(timeOffset);
// Apply a gentle oscillation over depth (Z) for dynamic effect
const depthOscillation = z * 0.5;
positions[i * 3] = newX;
positions[i * 3 + 1] = newY;
positions[i * 3 + 2] = Math.sin(depthOscillation + timeOffset * 0.8) * 2; // Subtle z-wave
}
// Flag Three.js that the attributes have changed, triggering a necessary update
particlesMesh.geometry.attributes.position.needsUpdate = true;
}
/**
* Updates camera position based on mouse input (parallax/tilt effect).
*/
function updateCamera(delta) {
// Smoothly interpolate the camera target toward the current mouse position
camera.position.x += Math.sin(mouseX * 0.5) * delta * 0.1;
camera.position.y += Math.cos(mouseY * 0.5) * delta * 0.1;
// Smoothly update the camera's rotation/look target
camera.rotation.x = mouseY * 0.2;
camera.rotation.y = mouseX * 0.2;
// Reset position slightly to prevent drift and keep it centered on the galaxy
camera.position.x = Math.sin(mouseX) * 10 + (Math.cos(delta/5) * 2);
camera.position.y = Math.cos(mouseY) * 10;
}
/**
* Main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
const currentTime = performance.now();
// Calculate delta time (time elapsed since last frame) for smooth movement
let delta = (currentTime - lastTime) / 1000; // Delta in seconds
lastTime = currentTime;
// --- Updates ---
updateParticles();
updateCamera(delta);
// Rotate the starfield slowly around the center to enhance depth
starfieldParticles.rotation.y += 0.0002;
starfieldParticles.rotation.x += 0.0001;
// --- Rendering & Performance ---
renderer.render(scene, camera);
updateFPSCounter();
}
/**
* Calculates and displays the FPS counter.
*/
function updateFPSCounter() {
frameCount++;
const e
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy animation with 5000 particles that respond to mouse movement and include a starfield background with FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 24px;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
font-size: 14px;
margin-bottom: 8px;
line-height: 1.4;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
font-family: monospace;
font-size: 16px;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 30px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
text-align: center;
font-size: 14px;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive Galaxy Animation</h1>
<p>• 5000 colorful particles in spiral formation</p>
<p>• Mouse movement tilts the galaxy</p>
<p>• Starfield background with depth effect</p>
<p>• Real-time FPS counter</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0, lastTime: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 50, 150);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 100;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const galaxyRadius = 80;
const armCount = 4;
const armWidth = 15;
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy with spiral arms
for (let i = 0; i < particleCount; i++) {
const radius = Math.random() * galaxyRadius;
const angle = Math.random() * Math.PI * 2;
// Create spiral arms
const armAngle = (angle / (Math.PI * 2)) * armCount;
const armOffset = Math.sin(armAngle * 3) * armWidth;
const x = Math.cos(angle) * radius + armOffset;
const y = Math.sin(angle) * radius + armOffset;
const z = (Math.random() - 0.5) * 10;
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
// Color based on position
const color = new THREE.Color();
const hue = (radius / galaxyRadius) * 0.3 + Math.random() * 0.1;
color.setHSL(hue, 0.8, 0.5 + Math.random() * 0.3);
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
// Size based on distance from center
sizes[i] = 0.5 + (1 - radius / galaxyRadius) * 2;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Update particle system rotation
if (particleSystem) {
particleSystem.rotation.x = mouseY * 0.5;
particleSystem.rotation.y = mouseX * 0.5;
// Slowly rotate the galaxy
particleSystem.rotation.z += 0.001;
}
// Update controls
controls.update();
// Update FPS counter
updateFPS(delta);
// Render scene
renderer.render(scene, camera);
}
// Update FPS counter
function updateFPS(delta) {
stats.fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent
gemma4:e4b
This is a complex animation requiring advanced JavaScript physics/rendering knowledge. The solution uses Three.js to achieve the spiral galaxy effect, mouse-based camera control (tilt), and an FPS counter, all within a single HTML file.
### 🌌 Interactive Galaxy Particle Field
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: 'Consolas', monospace;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<!-- Import Three.js Library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Initialization ---
let scene, camera, renderer;
let particles;
const particleCount = 5000;
let mouseX = 0;
let mouseY = 0;
// FPS tracking variables
let frameCount = 0;
let lastTime = performance.now();
const fpsElement = document.getElementById('fpsCounter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// Scene Setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set initial camera position and look at origin
camera.position.set(0, 0, 150);
camera.lookAt(0, 0, 0);
// Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
// Create the elements
createParticles();
createStarfieldBackground();
// Start the animation loop
animate();
}
/**
* Handles window resizing to keep the aspect ratio correct.
*/
function onWindowResize() {
camera.viewport = { x: 0, y: 0, width: 1, height: 1 };
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Handles mouse movement for camera tilt effect.
* Maps screen coordinates to rotation degrees.
*/
function onDocumentMouseMove(event) {
// Normalize mouse position (-1 to +1 range)
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* Creates the galaxy particle system in a spiral formation.
*/
function createParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < particleCount; i++) {
// Calculate position based on spiral formula: r = a*theta, z = b*theta
// i / particleCount gives the normalized angle t (0 to 1)
const t = i / particleCount;
// Spiral parameters
const radius = Math.pow(t, 0.5) * 20; // Radial distance grows with time/index
const zPos = (Math.sin(t * 4) * 10); // Z variation
const xPos = Math.cos(t * 3) * radius; // X position
const yPos = Math.sin(t * 3) * radius * 0.5 + zPos * 0.2; // Y position
positions.push(xPos, yPos, zPos);
// Assign random colorful coordinates (for variation)
color.setHSL((i / particleCount) + Math.random() * 0.1, 0.8, 0.6);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup: PointsMaterial is good for simple particle spheres
const material = new THREE.PointsMaterial({
size: 1.5, // Size of the individual particles
vertexColors: true, // Use the colors assigned to vertices
transparent: true,
opacity: 0.8
});
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
/**
* Creates a simple background starfield using random points.
*/
function createStarfieldBackground() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < 10000; i++) {
// Create stars far away from the origin
const x = Math.random() * 2000 - 1000;
const y = Math.random() * 2000 - 1000;
const z = Math.random() * 2000 - 1000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a PointMaterial for the stars
const material = new THREE.PointsMaterial({
color: 0xaaaaaa,
size: 1,
transparent: true,
opacity: 0.7
});
const starfield = new THREE.Points(geometry, material);
scene.add(starfield);
}
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
// 1. Update Particle Movement (Rotation and Translation)
const clock = new THREE.Clock();
const elapsed = clock.getDelta();
// Continuous rotation for the galaxy effect
particles.rotation.x += 0.001;
particles.rotation.y += 0.002;
// Subtle scaling or pulsation (optional)
particles.scale.set(1 + Math.sin(elapsed * 0.5) * 0.02,
1 + Math.sin((elapsed * 0.5) - 2) * 0.02,
1 + Math.sin((elapsed * 0.5) + 2) * 0.02);
// 2. Camera Tilt Response (Mouse Input)
// Smoothly interpolate camera rotation towards the mouse input
camera.rotation.y += (mouseX * 0.001 - camera.rotation.y) * 0.1;
camera.rotation.x += (mouseY * 0.001 - camera.rotation.x) * 0.1;
// 3. Rendering and FPS Update
renderer.render(scene, camera);
updateFPS();
}
/**
* Updates the displayed Frame Rate Counter.
*/
function updateFPS() {
const currentTime = performance.now();
const deltaTime = currentTime - lastTime;
// Calculate FPS based on time elapsed since last frame
const fps = 1000 / (deltaTime / frameCount);
fpsElement.textContent = `FPS: ${Math.round(fps)}`;
frameCount++;
lastTime = currentTime;
// Reset counter every second to prevent overflow/miscalculation
if (deltaTime > 1000) {
frameCount = 0;
lastTime = currentTime;
}
}
// --- Execution Start ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy simulation with 5000 particles that respond to mouse movement and include a starfield background with FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000;
font-family: 'Arial', sans-serif;
}
canvas {
display: block;
}
#info {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-size: 14px;
background-color: rgba(0, 0, 0, 0.5);
padding: 10px;
border-radius: 5px;
pointer-events: none;
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: white;
font-size: 24px;
text-shadow: 0 0 10px rgba(255, 255, 255, 0.7);
pointer-events: none;
letter-spacing: 2px;
}
#controls {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
pointer-events: none;
}
</style>
</head>
<body>
<div id="title">INTERACTIVE GALAXY SIMULATION</div>
<div id="info">Particles: 5000 | FPS: <span id="fps">60</span></div>
<div id="controls">Move mouse to tilt the galaxy | Scroll to zoom</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let stats, clock;
let galaxyCenter = new THREE.Vector3(0, 0, 0);
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add lighting
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1, 1000);
pointLight.position.set(0, 0, 0);
scene.add(pointLight);
// Setup event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.addEventListener('wheel', onMouseWheel);
// Initialize clock for FPS counter
clock = new THREE.Clock();
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const galaxyRadius = 300;
// Create geometry and material for particles
const particlesGeometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create particle data
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position particles in spiral galaxy pattern
const radius = Math.sqrt(Math.random()) * galaxyRadius;
const angle = Math.random() * Math.PI * 2;
// Spiral arms with some randomness
const armAngle = angle + (Math.sin(angle * 0.5) * 0.5);
const spiralRadius = radius * (1 + Math.sin(armAngle * 3) * 0.3);
positions[i3] = Math.cos(armAngle) * spiralRadius;
positions[i3 + 1] = Math.sin(armAngle) * spiralRadius;
positions[i3 + 2] = (Math.random() - 0.5) * 20;
// Color variation
const color = new THREE.Color();
const hue = (Math.random() * 0.4) + 0.5; // Blue to purple range
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.3 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random particle size
sizes[i] = Math.random() * 2 + 0.5;
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particlesGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particlesGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create particle system
const particleMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
particleSystem = new THREE.Points(particlesGeometry, particleMaterial);
scene.add(particleSystem);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Mouse wheel zoom handler
function onMouseWheel(event) {
camera.position.z += event.deltaY * 0.01;
camera.position.z = Math.max(100, Math.min(1000, camera.position.z));
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update FPS counter
const delta = clock.getDelta();
const fps = Math.round(1 / delta);
document.getElementById('fps').textContent = fps;
// Rotate galaxy based on mouse position
if (particleSystem) {
particleSystem.rotation.x += (mouseY * 0.005);
particleSystem.rotation.y += (mouseX * 0.005);
// Add subtle pulsing effect
const time = Date.now() * 0.0001;
particleSystem.rotation.z = Math.sin(time) * 0.05;
}
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this Interactive Galaxy Animation:
1. **Galaxy Simulation**:
- 5000 colorful particles arranged in a spiral galaxy pattern
- Particles have varying colors, sizes, and positions for realism
- Smooth rotation animation with mouse interaction
2. **Interactive Elements**:
- Mouse movement tilts the galaxy (x and y rotation)
- Scroll wheel to zoom in/out
- Orbit controls for manual navigation
3. **Visual Enhancements**:
- Starfield background with 10,000 stars
- Colorful particles with varying hues (blue to purple)
- Smooth
gemma4:e4b
This is a complex animation that uses advanced Three.js techniques (Geometry manipulation, shaders/attributes for color, and event listeners for interaction).
Here is the complete code in a single HTML file. Save this as an `.html` file and open it in your browser.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Galaxy Particle Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 20px;
left: 20px;
color: white;
font-family: 'Arial', sans-serif;
font-size: 18px;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Setup Variables ---
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
const PARTICLE_COUNT = 5000;
let mouseX = 0, mouseY = 0;
let container = document.getElementById('fps-counter');
// --- FPS Tracking Variables ---
let frameCount = 0;
let lastTime = performance.now();
const fpsInterval = 1000 / 60; // Update FPS display at least 60 times per second
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000000, 0.0005); // Adds depth effect
// 2. Camera Setup (Perspective camera)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 0;
// 3. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// --- Create Particle Systems ---
createStarField();
createGalaxyParticles();
// 4. Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
// Start the animation loop
animate();
}
/**
* Creates a large, static starfield background particle system.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < 15000; i++) {
// Random position in a large cube area
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material using PointsMaterial for simple stars
const material = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
transparent: true,
opacity: 0.8
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
/**
* Creates the main galaxy particle system in a spiral shape.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Parameters for the spiral distribution
const maxRadius = 50;
const startAngle = 0;
const endAngle = Math.PI * 6; // A full rotation multiplied by 3
for (let i = 0; i < PARTICLE_COUNT; i++) {
// Calculate angle and radius for spiral distribution
// The formula r = a * theta creates the spiral shape
const theta = startAngle + (i / PARTICLE_COUNT) * (endAngle - startAngle);
let r = Math.sqrt(Math.random()) * maxRadius; // Radius scales with random factor
// Add slight variation to keep it somewhat volumetric/disk-like
r *= 0.8 + Math.random() * 0.4;
const x = r * Math.cos(theta);
const z = r * Math.sin(theta);
// Keep y (height) constrained for a thin disk structure
const y = (Math.random() - 0.5) * 2;
positions.push(x, y, z);
// Assign random colors (glowing blues/whites)
const color = new THREE.Color();
color.setHSL(Math.random(), Math.random(), 0.7); // HSL for good variation
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Store colors as a separate attribute (more efficient than using PointsMaterial)
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.5, // Smaller size for denser look
vertexColors: true, // Use the stored colors per vertex
transparent: true,
opacity: 0.9
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Handles window resizing to keep the canvas cover the viewport.
*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates mouse tracking variables.
* @param {MouseEvent} event - The mouse movement event.
*/
function onDocumentMouseMove(event) {
// Normalize coordinates to the range [-1, 1]
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* The main animation loop function.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now();
const delta = (time - lastTime) / 1000; // Time elapsed since last frame in seconds
lastTime = time;
// --- 1. Galaxy Rotation (Spiral Movement) ---
galaxyParticles.rotation.y += 0.0005 * delta * 60; // Rotate slowly around Y-axis
galaxyParticles.rotation.x += 0.0002 * delta * 30; // Slight pitch
// --- 2. Starfield Movement (Subtle parallax/slow rotation) ---
starFieldParticles.rotation.y += 0.00005 * delta * 60;
starFieldParticles.scale.set(1, 1, Math.pow(Math.sin(time / 5000), 2)); // Subtle breathing effect
// --- 3. Mouse Interaction (Camera Tilt) ---
// Interpolate camera position/rotation based on mouse input for smooth tilt
camera.position.x += (mouseX * 1 - camera.position.x) * 0.05;
camera.position.y += (mouseY * 0.5 - camera.position.y) * 0.05;
// Optional: Tilt the entire scene slightly based on mouse input for immersion
scene.rotation.z = mouseY * 0.01;
scene.rotation.x = -mouseX * 0.01;
// --- 4. Render and Update FPS ---
renderer.render(scene, camera);
updateFPSCounter(time);
}
/**
* Calculates and updates the visible FPS counter display.
* @param {number} currentTime - The current timestamp.
*/
function updateFPSCounter(currentTime) {
frameCount++;
const elapsed = (currentTime - lastTime) / 1000; // Time since start of frame count
if (elapsed >= 0.5 || (frameCount % 60 === 0)) {
let fps = Math.round(frameCount / elapsed);
container.textContent = `FPS: ${fps}`;
// Reset counters for next measurement cycle
frameCount = 0;
lastTime = currentTime;
}
}
// --- Initialization Call ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D galaxy animation with 5000 particles, mouse tilt response, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
cursor: pointer;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: rgba(255, 255, 255, 0.8);
font-size: 36px;
text-align: center;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
pointer-events: none;
opacity: 0.8;
}
#title span {
display: block;
font-size: 16px;
margin-top: 10px;
font-weight: normal;
letter-spacing: 2px;
}
.instructions {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
text-align: center;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 20px;
border-radius: 20px;
backdrop-filter: blur(5px);
}
</style>
</head>
<body>
<div id="container">
<div id="info">3D Galaxy Particle Animation</div>
<div id="fps-counter">FPS: 0</div>
<div id="title">INTERACTIVE GALAXY<br><span>Move your mouse to tilt the galaxy</span></div>
<div class="instructions">Move mouse to interact | Click to change particle color</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 50, 200);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 150;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
document.addEventListener('click', onDocumentClick);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.2,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const particles = new THREE.BufferGeometry();
const posArray = new Float32Array(particleCount * 3);
const colorArray = new Float32Array(particleCount * 3);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
// Position particles in a spiral pattern
const radius = Math.sqrt(Math.random()) * 50;
const angle = Math.random() * Math.PI * 2;
const x = Math.cos(angle) * radius;
const y = Math.sin(angle) * radius;
const z = (Math.random() - 0.5) * 10;
posArray[i * 3] = x;
posArray[i * 3 + 1] = y;
posArray[i * 3 + 2] = z;
// Color particles with galaxy-like colors
const hue = (Math.random() * 0.4) + 0.5; // Blue to purple range
const saturation = 0.8;
const lightness = Math.random() * 0.3 + 0.4;
const color = new THREE.Color(`hsl(${hue * 360}, ${saturation * 100}%, ${lightness * 100}%)`);
colorArray[i * 3] = color.r;
colorArray[i * 3 + 1] = color.g;
colorArray[i * 3 + 2] = color.b;
}
particles.setAttribute('position', new THREE.BufferAttribute(posArray, 3));
particles.setAttribute('color', new THREE.BufferAttribute(colorArray, 3));
const particleMaterial = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
particleSystem = new THREE.Points(particles, particleMaterial);
scene.add(particleSystem);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Handle click to change particle color
function onDocumentClick() {
const hue = Math.random();
const particles = particleSystem.geometry.attributes.position.array;
for (let i = 0; i < particles.length; i += 3) {
const x = particles[i];
const y = particles[i + 1];
const z = particles[i + 2];
// Create a color based on position
const distance = Math.sqrt(x * x + y * y);
const newHue = (hue + distance / 100) % 1;
const color = new THREE.Color(`hsl(${newHue * 360}, 80%, 60%)`);
// Update the color in the buffer
particleSystem.geometry.attributes.color.setXYZ(
i / 3,
color.r,
color.g,
color.b
);
}
particleSystem.geometry.attributes.color.needsUpdate = true;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate particles
particleSystem.rotation.x += 0.0005;
particleSystem.rotation.y += 0.001;
// Mouse tilt effect
came
gemma4:e4b
This task requires advanced use of Three.js features like geometry manipulation, event handling, and rendering loops. The following single HTML file contains the complete solution.
### Interactive Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particles</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: fixed;
top: 10px;
left: 10px;
color: white;
font-family: 'Arial', sans-serif;
background-color: rgba(0, 0, 0, 0.6);
padding: 5px 10px;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
const NUM_PARTICLES = 5000;
// Mouse movement tracking for tilt effect
const mouse = new THREE.Vector2();
const targetRotation = new THREE.Euler(0, 0, 0);
// FPS Counter variables
let frameCount = 0;
let lastTime = performance.now();
const fpsCounterElement = document.getElementById('fps-counter');
/**
* Initializes the Three.js scene elements.
*/
function init() {
// Scene Setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set initial camera position
camera.position.z = 5;
// Lighting (optional, but good practice)
scene.add(new THREE.AmbientLight(0x333366)); // Deep ambient glow
createGalaxy();
createStarField();
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove);
}
/**
* Creates the main galaxy spiral particle system.
*/
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < NUM_PARTICLES; i++) {
// Spiral calculation logic: R depends on the angle (theta)
// This creates a clear spiral shape when projected into 3D space.
const theta = Math.random() * Math.PI * 2; // Full circle angle
// Radius increases with the "turn" of the galaxy
const radiusFactor = Math.pow(i / NUM_PARTICLES, 0.5);
// Position calculation (simulating a spiral disk)
const x = Math.cos(theta) * radiusFactor * 10;
const y = Math.sin(theta) * radiusFactor * 2 + (Math.random() - 0.5) * 1; // Slight vertical variation
const z = Math.cos(theta * 3) * radiusFactor * 8; // Z depth for the spiral twist
positions.push(x, y, z);
// Assign random colors and map them to the color array
color.setHSL(Math.random(), 0.6 + Math.random() * 0.3, 0.5);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.05,
vertexColors: true, // Use the colors we assigned to the vertices
transparent: true,
opacity: 0.8,
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a dense, distant starfield background using simple points.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
// Starfield size: A large cube encompassing the scene
for (let i = 0; i < 30000; i++) {
// Random coordinates within a large box (-50 to 50)
positions.push(
Math.random() * 100 - 50,
Math.random() * 100 - 50,
Math.random() * 100 - 50
);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
color: 0xaaaaaa, // Dim white/gray stars
size: 0.1,
transparent: true,
blending: THREE.AdditiveBlending // Makes them glow slightly when overlapping
});
starFieldParticles = new THREE.Points(geometry, material);
// Push the starfield far back so it doesn't interfere with the main action
starFieldParticles.position.set(0, 0, -50);
scene.add(starFieldParticles);
}
/**
* Handles window resizing to keep the canvas fitting.
*/
function onWindowResize() {
camera.viewport = camera.domElement;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Handles mouse movement to calculate tilt effect.
*/
function onMouseMove(event) {
// Normalize mouse coordinates (-1 to +1)
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// Calculate target rotations based on mouse input
// We use a damping factor to make the movement smooth and not jarring.
targetRotation.set(mouse.x * 0.1, Math.PI / 4 - (event.clientY / window.innerHeight) * 0.15, 0);
}
/**
* The main animation loop.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now();
const deltaTime = time - lastTime;
lastTime = time;
// --- Particle Animation Logic ---
// 1. Galaxy Rotation (Spinning)
galaxyParticles.rotation.y += 0.0005 * (deltaTime / 16);
galaxyParticles.rotation.x += 0.0002 * (deltaTime / 16);
// 2. Starfield Movement (Subtle drift/parallax)
starFieldParticles.rotation.y += 0.00005;
starFieldParticles.position.z += 0.00001;
// --- Mouse Tilt Implementation ---
// Smoothly interpolate the scene's rotation towards the target (mouse input).
const currentRotation = new THREE.Euler(scene.rotation.x, scene.rotation.y, scene.rotation.z);
// Use a smooth lerp factor (e.g., 0.05) for gentle movement
scene.rotation.x += (targetRotation.x - currentRotation.x) * 0.1;
scene.rotation.y += (targetRotation.y - currentRotation.y) * 0.1;
// --- FPS Counter Update ---
frameCount++;
if (time >= lastTime + 1000) { // Check every second
const fps = Math.round(frameCount / ((time - lastTime) / 1000));
fpsCounterElement.textContent = `FPS: ${fps}`;
frameCount = 0;
}
// Render the scene
renderer.render(scene, camera);
}
// --- Execution ---
init();
animate();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from the CDN, you'll need to write some code that sets up a scene with particles, a starfield background, and responds to mouse movement for rotation. Below is a simple example of how you can achieve this in a single HTML file:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Set up the scene, camera, and renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create a starfield background
const starsGeometry = new THREE.BufferGeometry().addAttribute('position', new THREE.Float32BufferAttribute(new Float32Array([...new Array(5000)].map(() => (Math.random() - 0.5) * 2)), 3));
const starMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1 });
const stars = new THREE.Points(starsGeometry, starMaterial);
scene.add(stars);
// Create particles
const particleCount = 5000;
const positions = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
positions[i * 3] = (Math.random() - 0.5) * 10;
positions[i * 3 + 1] = (Math.random() - 0.5) * 10;
positions[i * 3 + 2] = (Math.random() - 0.5) * 10;
}
const particleGeometry = new THREE.BufferGeometry();
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const particleMaterial = new THREE.PointsMaterial({ color: Math.random(), size: 0.1 });
const particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
// Position the camera and add lighting
camera.position.z = 5;
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(-1, 2, 4).normalize();
scene.add(light);
// Handle window resize
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animate the particles and respond to mouse movement
function animate() {
requestAnimationFrame(animate);
// Rotate the particles based on mouse movement
const mouseX = (event.clientX / window.innerWidth) * 2 - 1;
const mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
camera.rotation.x = mouseY * 0.1;
camera.rotation.y = mouseX * 0.1;
// Render the scene
renderer.render(scene, camera);
}
animate();
// Show FPS counter in the corner
let fps = 0;
const startTime = Date.now();
function tick() {
requestAnimationFrame(tick);
const elapsedTime = (Date.now() - startTime) / 1000;
const frameRate = Math.round(1 / elapsedTime);
fps = frameRate;
}
tick();
</script>
</body>
</html>
```
This code sets up a basic Three.js scene with particles that move in response to mouse movement, a starfield background, and includes an FPS counter in the corner. The particles are colorful due to random color assignment. This example uses simple geometries and materials for demonstration purposes; you can enhance the visual quality by using more complex geometries and materials or adding additional effects.
qwen3:32b-q4_K_M
Here's a complete single HTML file that creates an interactive 3D galaxy particle animation with all the requested features using Three.js:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Galaxy Particle Animation</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { display: block; }
#stats { position: absolute; top: 0; left: 0; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/stats.js@latest/stats.min.js"></script>
<script>
let scene, camera, renderer, galaxy, stars, stats;
let mouseX = 0, mouseY = 0;
init();
animate();
function init() {
// Scene setup
scene = new THREE.Scene();
// Camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// Renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.outputColorSpace = THREE.LinearSRGBColorSpace;
document.body.appendChild(renderer.domElement);
// Stats
stats = new Stats();
stats.showPanel(0);
document.body.appendChild(stats.dom);
qwen3-coder:30b
# Interactive Galaxy Particle Animation
I'll create an impressive 3D particle animation that simulates a galaxy with 5000 colorful particles responding to mouse movement. The solution will be contained in a single HTML file using Three.js from CDN.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Galaxy Particle Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
max-width: 300px;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff758c);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 117, 140, 0.5);
}
#info p {
font-size: 0.9rem;
margin-bottom: 10px;
line-height: 1.5;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
font-family: monospace;
font-size: 1.2rem;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 30px;
backdrop-filter: blur(5px);
text-align: center;
font-size: 0.9rem;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Galaxy Particle Animation</h1>
<p>This interactive visualization features:</p>
<p>• <span class="highlight">5000</span> colorful particles in a spiral galaxy pattern</p>
<p>• <span class="highlight">Real-time mouse interaction</span> - tilt the galaxy</p>
<p>• <span class="highlight">Starfield background</span> with twinkling stars</p>
<p>• <span class="highlight">Smooth animations</span> and performance optimization</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Click to change color palette</div>
</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats;
let colorPalette = [
new THREE.Color(0xff7eb3), // Pink
new THREE.Color(0x4facfe), // Blue
new THREE.Color(0x00f2fe), // Cyan
new THREE.Color(0x834d9b), // Purple
new THREE.Color(0xf6d365) // Yellow
];
let currentPalette = 0;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.addEventListener('click', changeColorPalette);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleGeometry = new THREE.BufferGeometry();
const particleMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
// Create spiral galaxy pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(i / particleCount) * 150;
const angle = i * 0.2 + (Math.sin(i * 0.01) * 0.5);
// Position particles in spiral
const x = Math.cos(angle) * radius;
const y = Math.sin(angle) * radius;
const z = Math.sin(i * 0.05) * 20;
positions[i3] = x;
positions[i3 + 1] = y;
positions[i3 + 2] = z;
// Assign colors based on position and palette
const colorIndex = i % colorPalette.length;
const color = colorPalette[colorIndex];
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Window resize handler
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Change color palette
function changeColorPalette() {
currentPalette = (currentPalette + 1) % 3;
const newColors = [];
for (let i = 0; i < particleCount; i++) {
let color;
switch(currentPalette) {
case 0: // Pastel
color = new THREE.Color(
Math.random() * 0.5 + 0.5,
Math.random() * 0.5 + 0.5,
Math.random() * 0.5 + 0.5
);
break;
case 1: // Neon
color = new THREE.Color(
Math.random() > 0.5 ? 1 : 0,
Math.random() > 0.5 ? 1 : 0,
Math.random() > 0.5 ? 1 : 0
);
break;
case 2: // Sunset
color = new THREE.Color(
Math.random() * 0.8 + 0.2,
Math.random() * 0.5,
Math.random() * 0.3
);
break;
}
gemma4:e4b
This implementation uses modern JavaScript practices, Three.js's performance features (BufferGeometry), and combines mathematical functions to create the spiral galaxy effect, while integrating mouse tracking and FPS monitoring.
Due to the complexity of combining all these elements into one self-contained file, the code is substantial but fully functional when saved as an `.html` file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fps-counter {
position: fixed;
top: 10px;
left: 10px;
color: rgba(255, 255, 255, 0.7);
font-family: 'Arial', sans-serif;
padding: 8px 15px;
background-color: rgba(0, 0, 0, 0.4);
border-radius: 5px;
user-select: none;
z-index: 100; /* Ensure it's above the canvas */
}
</style>
</head>
<body>
<div id="fps-counter">FPS: --</div>
<!-- Include Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starField;
const NUM_GALAXY_PARTICLES = 5000;
const STAR_COUNT = 20000;
// Mouse interaction tracking
let mouseX = 0.0;
let mouseY = 0.0;
// Performance tracking
let lastTime = performance.now();
let frameCount = 0;
const fpsElement = document.getElementById('fps-counter');
/**
* Initializes the Three.js environment.
*/
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set camera position and initial look
camera.position.z = 50;
// 2. Create Objects
createGalaxyParticles();
createStarField();
// 3. Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onMouseMove, false);
}
/**
* Handles window resizing to keep the aspect ratio correct.
*/
function onWindowResize() {
camera.viewport = new THREE.Vector2(window.innerWidth, window.innerHeight);
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
/**
* Tracks mouse movement for interactive camera tilt.
*/
function onMouseMove(event) {
// Normalize coordinates to range [-1, 1]
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* Generates the particles forming a spiral galaxy structure.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Base particle material (small, brightly colored points)
const size = 0.5; // Size of the points
const colorMaterial = new THREE.PointsMaterial({
size: size,
vertexColors: true, // Use per-particle coloring
blending: THREE.AdditiveBlending, // Makes colors glow when overlapping
transparent: true,
depthWrite: false // Improves blending quality for particle systems
});
// --- Spiral Generation Logic (Parametric) ---
for (let i = 0; i < NUM_GALAXY_PARTICLES; i++) {
// Parameter 't' determines the position along the spiral curve
const t = Math.random() * Math.PI * 8; // Range of rotation
// Randomize distance from center for depth variation
const r = Math.pow(Math.random(), 1.5) * 20;
// Calculate coordinates using polar to cartesian conversion, modified for a spiral:
// x = r * cos(t + k*r)
// y = r * sin(t + k*r)
// z = offset based on the curve
const spiralFactor = 0.5; // Controls how tight the spiral is
const x = Math.cos(t + r * spiralFactor) * (r + Math.random() * 5);
const y = Math.sin(t + r * spiralFactor) * (r + Math.random() * 5);
// Z dimension creates the depth and spread of the galaxy
const z = Math.cos(t / 2) * r;
positions.push(x, y, z);
// Assign random vibrant color (HSL or RGB for glow effect)
const color = new THREE.Color();
color.setHSL(Math.random(), 1.0, Math.random() * 0.5 + 0.5); // Saturation and Lightness high
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
galaxyParticles = new THREE.Points(geometry, colorMaterial);
scene.add(galaxyParticles);
}
/**
* Creates a dense, random starfield background using points.
*/
function createStarField() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < STAR_COUNT; i++) {
// Distribute stars widely in a large cube/sphere
const x = Math.random() * 200 - 100;
const y = Math.random() * 200 - 100;
const z = Math.random() * 200 - 100;
positions.push(x, y, z);
}
// Star material: small, white, subtle glow (Additive)
const starMaterial = new THREE.PointsMaterial({
size: 0.3,
color: 0xaaaaee, // Light blue/white color
transparent: true,
blending: THREE.AdditiveBlending,
depthWrite: false
});
starField = new THREE.Points(geometry, starMaterial);
scene.add(starField);
}
/**
* The main animation loop. Handles rendering, movement, and physics.
*/
function animate() {
requestAnimationFrame(animate);
const currentTime = performance.now();
const delta = (currentTime - lastTime) / 1000; // Delta time in seconds
lastTime = currentTime;
// --- Galaxy Movement ---
// Continuous rotation to simulate the flow of a galaxy
galaxyParticles.rotation.x += 0.0005 * delta;
galaxyParticles.rotation.y += 0.001 * delta;
// Subtle scaling for breathing effect
galaxyParticles.scale.set(1, 1, 1).add(Math.sin(currentTime / 2000) * 0.05);
// --- Starfield Movement (Parallax/Rotation) ---
starField.rotation.y += 0.0001;
starField.position.z = Math.cos(currentTime / 3000) * 2; // Gentle bobbing motion
// --- Camera Interaction & Tilt ---
// Smoothly move camera based on mouse input (parallax effect)
camera.rotation.y += (mouseX - camera.rotation.y) * 0.01;
camera.position.x = Math.sin(currentTime / 5000) * 2 + (mouseX * 0.5); // Gentle horizontal sway based on mouse
camera.lookAt(scene.position);
// --- Rendering ---
renderer.render(scene, camera);
// --- FPS Counter Update ---
updateFPS(delta);
}
/**
* Calculates and displays the current Frames Per Second (FPS).
*/
function updateFPS(deltaTime) {
frameCount++;
const elapsed = (performance.now() - lastTime) / 1000; // Time since first measurement
if (elapsed >= 1) {
let fps = Math.round(frameCount / elapsed);
fpsElement.textContent = `FPS: ${Math.max(1, fps)}`; // Ensure minimum display of 1 FPS
// Reset counters for the next second calculation
frameCount = 0;
}
}
// --- Initialization Call ---
init();
animate();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN, you can follow this example. This example includes a starfield background, colorful particles rotating in a spiral galaxy-like pattern, and a FPS counter that responds to mouse movement for tilting effects.
Here's the complete code:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create a starfield background
const starsGeometry = new THREE.BufferGeometry().addAttribute('position', new THREE.Float32BufferAttribute(new Float32Array(5000 * 3), { itemSize: 3 }));
const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
const starField = new THREE.Points(starsGeometry, starsMaterial);
scene.add(starField);
// Create particles
const particleCount = 5000;
const positions = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
positions[i * 3] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 1] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 2] = (Math.random() - 0.5) * 2000;
}
const particlesGeometry = new THREE.BufferGeometry();
particlesGeometry.addAttribute('position', new THREE.Float32BufferAttribute(positions, { itemSize: 3 }));
const particlesMaterial = new THREE.PointsMaterial({ color: 0x8888ff, size: 2 });
const particles = new THREE.Points(particlesGeometry, particlesMaterial);
scene.add(particles);
// Position the camera
camera.position.z = 1500;
// Handle window resize
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const elapsedTime = clock.getElapsedTime();
// Rotate particles and camera in response to mouse movement
const tiltFactor = 0.01;
const rotationSpeed = 0.01;
particles.rotation.x += rotationSpeed;
particles.rotation.y += rotationSpeed;
camera.position.z += (mouseX - window.innerWidth / 2) * tiltFactor;
camera.position.x += (mouseY - window.innerHeight / 2) * tiltFactor;
// Render the scene
renderer.render(scene, camera);
}
let mouseX = 0, mouseY = 0;
document.addEventListener('mousemove', function(event) {
mouseX = event.clientX;
mouseY = event.clientY;
});
animate();
</script>
</body>
</html>
```
This code sets up a basic Three.js scene with a starfield background and 5000 particles that rotate in response to mouse movement, creating a dynamic and visually impressive animation. The FPS counter is not included here because it requires additional logic to display the frame rate; however, you can easily add an overlay or text element to show the FPS if desired using Three.js's `Stats` class for performance monitoring.
qwen3-coder:30b
# Interactive Galaxy Particle Animation
I'll create an immersive 3D particle galaxy animation with mouse interaction and starfield background using Three.js. Here's the complete solution:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/stats.js@0.17.0/build/stats.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
max-width: 300px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 24px;
margin-bottom: 10px;
background: linear-gradient(to right, #ff8a00, #da1b60);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 138, 0, 0.3);
}
#info p {
font-size: 14px;
line-height: 1.5;
margin-bottom: 15px;
}
#stats {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.controls {
display: flex;
gap: 10px;
margin-top: 10px;
}
.control-btn {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
padding: 8px 12px;
border-radius: 5px;
cursor: pointer;
transition: all 0.3s ease;
}
.control-btn:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateY(-2px);
}
#loading {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: #000;
z-index: 1000;
transition: opacity 1s ease;
}
.spinner {
width: 50px;
height: 50px;
border: 5px solid rgba(255, 255, 255, 0.1);
border-top: 5px solid #ff8a00;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Galaxy Particle Animation</h1>
<p>Interactive 3D galaxy with 5,000 colorful particles rotating in a spiral pattern.</p>
<p>Move your mouse to tilt the galaxy. The background features a starfield for depth.</p>
<div class="controls">
<button id="pauseBtn" class="control-btn">Pause</button>
<button id="resetBtn" class="control-btn">Reset</button>
</div>
</div>
<div id="stats"></div>
<div id="loading">
<div class="spinner"></div>
</div>
</div>
<script>
// Main variables
let scene, camera, renderer, particles, stats;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let galaxyRadius = 100;
let rotationSpeed = 0.002;
let paused = false;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 300;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Initialize stats
initStats();
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
document.getElementById('pauseBtn').addEventListener('click', togglePause);
document.getElementById('resetBtn').addEventListener('click', resetGalaxy);
// Hide loading screen after a delay
setTimeout(() => {
document.getElementById('loading').style.opacity = '0';
setTimeout(() => {
document.getElementById('loading').style.display = 'none';
}, 1000);
}, 1500);
// Start animation
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleGeometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position particles in a spiral pattern
const radius = Math.random() * galaxyRadius;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) * 0.6;
color.setHSL(hue, 1, 0.5 + Math.random() * 0.3);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Vary particle sizes
sizes[i] = Math.random() * 2 + 0.5;
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particleGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const particleMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
}
// Initialize stats
function initStats() {
stats = new Stats();
stats.showPanel(0); // 0: fps, 1: ms, 2: mb
document.getElementById('stats').appendChild(stats.dom);
stats.dom.style.cssText = 'position:absolute;top:0px;left:0px;cursor:pointer;opacity:0.9;z-index:100';
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.01;
mouseY = (event.clientY - windowHalfY) * 0.01;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.
gemma4:e4b
This is a complex and resource-intensive animation. To ensure maximum compatibility and modern web standards, I will use the CDN version of Three.js.
The resulting single HTML file contains all the necessary CSS, JavaScript logic, particle generation, interactivity handlers, and the animation loop.
### ✨ Interactive Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Nebula</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000010; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 20px;
left: 20px;
padding: 8px 15px;
background-color: rgba(0, 0, 0, 0.6);
color: #ffffff;
font-family: 'Courier New', monospace;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 60</div>
<!-- Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// ==========================================
// GLOBAL SETUP AND INITIALIZATION
// ==========================================
let scene, camera, renderer;
let galaxyParticles, starParticles;
const particleCount = 5000; // For the main galaxy spiral
const starCount = 15000; // For the background starfield
// Variables for interactivity and animation state
let mouseX = 0;
let mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
// FPS tracking variables
let lastTime = performance.now();
let frameCount = 0;
const fpsElement = document.getElementById('fps-counter');
function init() {
// Setup Scene, Camera, Renderer
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set initial camera position (looking into the galaxy)
camera.position.z = 50;
// Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Create Particle Systems
createGalaxySpiral();
createStarfield();
// Start the animation loop
animate();
}
// ==========================================
// PARTICLE GENERATION FUNCTIONS
// ==========================================
/**
* Creates the main galaxy spiral particle system.
*/
function createGalaxySpiral() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
for (let i = 0; i < particleCount; i++) {
// Calculate position for a spiral shape
// Radius increases with the angle, creating the spiral effect
const theta = Math.random() * Math.PI * 2; // Angle (0 to 360 degrees)
let radius = Math.pow(Math.random(), 1.5) * 80; // Controls overall size
// Spiral factor: The distance from the center increases as 'a' increases
const a = i / particleCount * 2 * Math.PI;
radius *= (1 + (a / (Math.PI * 3))); // Scale based on angle
// Use sine/cosine for X and Y coordinates, giving it depth
const x = radius * Math.cos(theta);
const y = radius * Math.sin(theta) * 0.5; // Compress vertical axis slightly
const z = a * 10 + (Math.random() - 0.5) * 20; // Depth component
positions.push(x, y, z);
// Assign random colors and varying opacity for depth effect
const color = new THREE.Color();
color.setHSL(Math.random(), 1.0, Math.random() * 0.5 + 0.2); // HSL for vibrant colors
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup
const material = new THREE.PointsMaterial({
size: 0.8,
vertexColors: true, // Use the colors defined in the geometry
transparent: true,
opacity: 0.9,
blending: THREE.AdditiveBlending // Makes particles glow nicely
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a static starfield background.
*/
function createStarfield() {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < starCount; i++) {
// Distribute stars across a large cube volume
const x = (Math.random() - 0.5) * 4000;
const y = (Math.random() - 0.5) * 4000;
const z = (Math.random() - 0.5) * 4000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material setup: small, white, twinkling points
const material = new THREE.PointsMaterial({
size: 1,
color: 0xaaaaaa,
transparent: true,
opacity: 0.8
});
starParticles = new THREE.Points(geometry, material);
scene.add(starParticles);
}
// ==========================================
// EVENT HANDLERS & UTILITIES
// ==========================================
function onWindowResize() {
camera.viewport.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates the mouse tracking variables.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.5; // Normalize movement range
mouseY = (event.clientY - windowHalfY) * 0.5;
}
/**
* Updates the FPS counter display.
*/
function updateFPS(deltaTime) {
const fps = Math.round(1 / deltaTime);
fpsElement.textContent = `FPS: ${fps}`;
}
// ==========================================
// ANIMATION LOOP (The core rendering function)
// ==========================================
function animate() {
requestAnimationFrame(animate);
const currentTime = performance.now();
const deltaTime = currentTime - lastTime;
lastTime = currentTime;
// 1. Interactivity Logic: Rotate camera based on mouse position
camera.rotation.x += (mouseY * 0.0005) * 0.2;
camera.rotation.y += (mouseX * 0.0005) * 0.2;
// 2. Galaxy Animation: Slow rotation and subtle pulsing movement
const time = Date.now() * 0.unscaled / 1000;
galaxyParticles.rotation.x += 0.0001;
galaxyParticles.rotation.y += 0.0002 + (Math.sin(time * 0.1) * 0.0005);
// Scale the entire galaxy slightly over time for a breathing effect
const scaleFactor = 1 + Math.sin(time * 0.3) * 0.005;
galaxyParticles.scale.set(scaleFactor, scaleFactor, scaleFactor);
// 3. Starfield Animation: Slow, large-scale drift
starParticles.rotation.y += 0.00005;
starParticles.position.z += Math.sin(time * 0.1) * 0.05; // Drift back and forth
// 4. Rendering and Performance Update
renderer.render(scene, camera);
updateFPS(deltaTime);
}
// --- Start the application ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy animation with 5000 colorful particles that respond to mouse movement and include a starfield background with FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
margin: 5px 0;
font-size: 0.9rem;
opacity: 0.8;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
font-family: monospace;
font-size: 1.2rem;
}
#controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 30px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
gap: 15px;
}
#controls button {
background: linear-gradient(to right, #ff7eb3, #ff70a6);
border: none;
padding: 8px 15px;
border-radius: 20px;
color: white;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
}
#controls button:hover {
transform: scale(1.05);
box-shadow: 0 0 15px rgba(255, 110, 179, 0.5);
}
.particle-count {
position: absolute;
bottom: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
font-size: 0.9rem;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive Galaxy Animation</h1>
<p>5000 colorful particles rotating in a spiral galaxy</p>
<p>Move your mouse to tilt the galaxy</p>
<p>Experience the cosmic dance of stars</p>
</div>
<div id="fps-counter">FPS: 60</div>
<div class="particle-count">Particles: 5,000</div>
<div id="controls">
<button id="speed-up">Speed Up</button>
<button id="slow-down">Slow Down</button>
<button id="reset">Reset</button>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let rotationSpeed = 0.001;
let clock = new THREE.Clock();
let stats = { fps: 60, lastFpsUpdate: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create particles
createParticles();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Setup controls
setupControls();
// Setup buttons
document.getElementById('speed-up').addEventListener('click', () => {
rotationSpeed = Math.min(rotationSpeed + 0.0005, 0.01);
});
document.getElementById('slow-down').addEventListener('click', () => {
rotationSpeed = Math.max(rotationSpeed - 0.0005, 0.0001);
});
document.getElementById('reset').addEventListener('click', () => {
rotationSpeed = 0.001;
});
// Start animation
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createParticles() {
const particleGeometry = new THREE.BufferGeometry();
const particleMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
// Create spiral galaxy pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 4;
const height = (Math.random() - 0.5) * 100;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) * 0.5 + 0.5; // Range from blue to red
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.3 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
}
// Setup controls
function setupControls() {
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.enableZoom = false;
controls.enablePan = false;
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.01;
mouseY = (event.clientY - windowHalfY) * 0.01;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.
gemma4:e4b
This solution provides a single, self-contained HTML file that uses Three.js for a visually complex, interactive 3D particle animation simulating a rotating galaxy with a starfield background.
### Interactive Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Swirl</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 20px;
left: 20px;
color: white;
font-family: monospace;
padding: 10px;
background: rgba(0, 0, 0, 0.5);
border-radius: 5px;
}
</style>
<!-- Three.js Library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
let mouseX = 0, mouseY = 0;
// FPS Tracking variables
let frameCount = 0;
let lastTime = performance.now();
const fpsCounterElement = document.getElementById('fps-counter');
// --- Initialization Function ---
function init() {
// Set up scene, camera, and renderer
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Set camera position
camera.position.z = 50;
// --- Create Particle Systems ---
createGalaxyParticles(5000);
createStarfield(20000);
// Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onMouseMove, false);
// Start the animation loop
animate();
}
/**
* Creates the main galaxy spiral particle system.
* Uses a parametric equation to create the spiral shape.
* @param {number} count - Number of particles.
*/
function createGalaxyParticles(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Parameters for the spiral: R = r * e^(theta/b), Z = z_offset
const numSegments = 50; // Number of rotational steps
const maxAngle = Math.PI * 8; // Total rotation range (full galaxy view)
for (let i = 0; i < count; i++) {
// Calculate angle and segment index based on particle ID for better distribution
let theta = (i / count) * maxAngle;
let segmentIndex = Math.floor(i / (count / numSegments)); // Controls the 'tightness' of the spiral
// Spiral function: Radius increases with angle (theta) and segments
const radius = 5 + (segmentIndex * 0.1) * Math.sin(theta / 2);
// Calculate positions using polar coordinates
const x = radius * Math.cos(theta);
const y = radius * Math.sin(theta) * 0.5; // Flatten the spiral vertically
const z = (i % 100 - 50) / 50; // Slight depth variation
positions.push(x, y, z);
// Color calculation: Use a gradient based on position/index
const colorHue = i * 0.02 + Math.random() * 0.1;
const color = new THREE.Color().setHSL(colorHue % 1, 0.8, 0.7);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup: Use PointsMaterial with vertex colors enabled
const material = new THREE.PointsMaterial({
size: 0.8 + Math.random() * 1.5, // Slightly varied size
vertexColors: true,
transparent: true,
opacity: 0.9
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a random starfield background using particles.
* @param {number} count - Number of stars to generate.
*/
function createStarfield(count) {
const geometry = new THREE.SphereGeometry(1000, 32, 32); // Large bounding box
const positions = [];
for (let i = 0; i < count; i++) {
// Random coordinates within a massive sphere/cube area
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a simple material for stars
const material = new THREE.PointsMaterial({
size: 1,
color: 0xffffff,
transparent: true,
blending: THREE.AdditiveBlending // Makes the stars glow better
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
// --- Event Handlers and Loop Logic ---
/**
* Handles window resizing.
*/
function onWindowResize() {
camera.viewport.setSize(window.innerWidth / 2, window.innerHeight / 2);
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Tracks mouse movement to influence camera angle.
* @param {MouseEvent} event - The mouse move event.
*/
function onMouseMove(event) {
// Normalize coordinates from -1 to 1 range for better control
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* Main animation loop function.
*/
function animate(time) {
requestAnimationFrame(() => animate(time));
// --- Animation Updates ---
// 1. Galaxy Rotation (Self-rotation and gentle movement)
galaxyParticles.rotation.y += 0.0002;
galaxyParticles.rotation.z += 0.0001;
// 2. Starfield Drift/Rotation
starfieldParticles.rotation.y += 0.00005;
starfieldParticles.rotation.x += 0.00002;
// 3. Camera Tilt (Mouse interaction)
// Smoothly interpolate the camera rotation based on mouse position
camera.rotation.y += (mouseX * 0.01 - camera.rotation.y) * 0.05;
camera.rotation.x += (mouseY * 0.01 - camera.rotation.x) * 0.05;
// Render the scene
renderer.render(scene, camera);
// --- FPS Counter Update ---
updateFPS(time);
}
/**
* Calculates and displays the current frame rate.
* @param {number} time - The current performance time.
*/
function updateFPS(time) {
const delta = time - lastTime;
frameCount++;
// Calculate FPS every 250ms (to prevent flickering/extreme changes)
if (delta >= 250) {
const fps = Math.round((1000 / delta) * frameCount);
fpsCounterElement.textContent = `FPS: ${fps}`;
// Reset for the next interval
frameCount = 0;
lastTime = time;
}
}
// --- Execution Start ---
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy animation with 5000 particles, mouse interaction, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
margin: 8px 0;
font-size: 1rem;
opacity: 0.8;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
font-size: 1.2rem;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
text-align: center;
font-size: 1rem;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>• 5000 colorful particles</p>
<p>• Spiral galaxy formation</p>
<p>• Mouse tilt interaction</p>
<p>• Starfield background</p>
</div>
<div id="fps-counter">FPS: 60</div>
<div id="instructions">Move your mouse to tilt the galaxy | Click and drag to rotate</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 60 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
2000
);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create the galaxy particle system
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy parameters
const radius = 200;
const arms = 4;
const armWidth = 20;
const spiralFactor = 0.1;
const maxRadius = radius * 1.5;
// Create particles in spiral formation
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position in spiral
const angle = Math.random() * Math.PI * 2;
const armAngle = Math.floor(Math.random() * arms) * (Math.PI * 2 / arms);
const r = Math.random() * maxRadius;
// Spiral effect
const spiralOffset = Math.sin(r * spiralFactor) * armWidth;
const x = Math.cos(armAngle + angle) * (r + spiralOffset);
const z = Math.sin(armAngle + angle) * (r + spiralOffset);
const y = (Math.random() - 0.5) * 30;
positions[i3] = x;
positions[i3 + 1] = y;
positions[i3 + 2] = z;
// Color with gradient from blue to yellow
const color = new THREE.Color();
const hue = (Math.sin(r * 0.02) * 0.5 + 0.5) * 0.1; // Blue to yellow
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Size variation
sizes[i] = Math.random() * 3 + 1;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Mouse movement handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate particles slowly
if (particleSystem) {
particleSystem.rotation.y += 0.001;
// Mouse tilt effect
camera.position.x += (mouseX * 50 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 50 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update controls
controls.update();
gemma4:e4b
This implementation uses a complex combination of geometries, shaders (implicitly via Three.js materials), event listeners, and performance tracking to achieve the desired effect.
Due to the size and complexity, the code is structured with clear comments explaining each major section: Setup, Particle Generation, Interaction Logic, Animation Loop, and Performance Tracking.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: rgba(255, 255, 255, 0.7);
font-family: 'Arial', sans-serif;
font-size: 18px;
padding: 10px;
background-color: rgba(0, 0, 0, 0.4);
border-radius: 5px;
user-select: none; /* Prevent text selection */
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// =========================================
// GLOBAL VARIABLES & SETUP
// =========================================
let camera, scene, renderer;
let galaxyParticles, starParticles;
const particleCount = 5000;
let mouseX = 0;
let mouseY = 0;
// Performance tracking variables
let fpsCounterElement = document.getElementById('fps-counter');
let frameCount = 0;
let lastTimestamp = performance.now();
/**
* Initializes the Three.js environment (Scene, Camera, Renderer).
*/
function init() {
// Scene setup
scene = new THREE.Scene();
// Camera setup
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 50;
// Renderer setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove);
// Create particle systems
createGalaxyParticles();
createStarfield();
// Start the animation loop
animate();
}
/**
* Creates the main galaxy spiral particle system.
*/
function createGalaxyParticles() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Parameters for a pleasing spiral shape
const maxRadius = 80;
const rotationFactor = 2; // Controls how many turns the spiral makes
const depthScale = 15;
for (let i = 0; i < particleCount; i++) {
// Normalized progress along the spiral path (0 to 1)
const t = i / particleCount;
// Spiral calculation: Radius scales and oscillates with angle
// R(t) = A + B * cos(k*t)
let radius = maxRadius * Math.sin(t * Math.PI);
radius += 20 * Math.cos(t * rotationFactor); // Add curvature
// Angle calculation (controls the spiral turn)
const angle = t * Math.PI * 4;
// Z position (depth)
const z = t * depthScale - (depthScale / 2);
// Cartesian coordinates for X, Y, Z
const x = radius * Math.cos(angle);
const y = radius * Math.sin(angle) * 0.5; // Flatten the vertical component slightly
const z_pos = z + (Math.random() - 0.5) * 10; // Add minor depth jitter
positions.push(x, y, z_pos);
// Color generation (Rainbow gradient based on position/index)
color.setHSL(t / particleCount * 0.8 + 0.2, 1.0, 0.5); // Hue changes from blueish to red
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Store colors in a custom attribute for easy shader/material use (though we use PointsMaterial here)
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors assigned to the vertices
opacity: 0.8,
transparent: true,
blending: THREE.AdditiveBlending
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a static background starfield using randomized points.
*/
function createStarfield() {
const geometry = new THREE.SphereGeometry(1000, 64, 64); // Large enough volume
const positions = [];
const color = new THREE.Color();
// Populate the sphere with random points
for (let i = 0; i < 50000; i++) {
// Random coordinates within a large cube/sphere
positions.push(
(Math.random() - 0.5) * 2000,
(Math.random() - 0.5) * 2000,
(Math.random() - 0.5) * 2000
);
}
const geometryStars = new THREE.BufferGeometry();
geometryStars.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const materialStars = new THREE.PointsMaterial({
size: 1,
color: 0xaaaaaa, // Faint white/gray light
transparent: true,
opacity: 0.6
});
starParticles = new THREE.Points(geometryStars, materialStars);
scene.add(starParticles);
}
/**
* Handles window resizing to keep the canvas full screen.
*/
function onWindowResize() {
camera.viewport.x = 0;
camera.viewport.y = 0;
camera.left = -1;
camera.right = 1;
camera.top = -1;
camera.bottom = 1;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.updateXR();
}
/**
* Handles mouse movement to tilt the camera/scene (Interaction).
*/
function onDocumentMouseMove(event) {
// Normalize coordinates (-1 to +1)
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* The main animation loop.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() * 0.001;
// --- 1. Particle Movement (Rotation & Drift) ---
if (galaxyParticles) {
const positions = galaxyParticles.geometry.attributes.position.array;
// Rotate the entire particle field around Y axis constantly
galaxyParticles.rotation.y += 0.0005;
galaxyParticles.rotation.x += 0.0002;
// Make particles "drift" slightly over time (creating a flow effect)
for (let i = 0; i < particleCount * 3; i += 3) {
positions[i + 2] += Math.sin(time * 0.5 + i / 100) * 0.001; // Z drift
}
galaxyParticles.geometry.attributes.position.needsUpdate = true;
} else {
// Fallback if particles aren't loaded yet
requestAnimationFrame(animate);
return;
}
// --- 2. Starfield Movement (Subtle slow rotation) ---
if (starParticles) {
starParticles.rotation.y += 0.00005;
starParticles.rotation.x = Math.sin(time * 0.1) * 0.01; // Gentle bobbing
}
// --- 3. Mouse Interaction (Camera Tilt/LookAt effect) ---
const targetRotationX = mouseY * 0.5;
const targetRotationY = mouseX * 0.5;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.05;
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.05;
// --- 4. Rendering and Performance Update ---
renderer.render(scene, camera);
updateFPS();
}
/**
* Calculates and displays the FPS counter in the corner.
*/
function updateFPS() {
const currentTime = performance.now();
const elapsed = currentTime - lastTimestamp;
frameCount++;
// Only calculate FPS every 500ms (or a fixed number of frames)
if (elapsed >= 500) {
const fps = Math.round(1000 / ((elapsed / frameCount)));
fpsCounterElement.textContent = `FPS: ${fps}`;
// Reset counters
frameCount = 0;
lastTimestamp = currentTime;
}
}
// =========================================
// START EXECUTION
// =========================================
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D galaxy animation using Three.js with 5000 particles rotating in a spiral pattern, responsive to mouse movement and featuring a starfield background.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
max-width: 300px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7e5f, #feb47b);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 126, 95, 0.3);
}
#info p {
font-size: 0.9rem;
margin-bottom: 15px;
line-height: 1.5;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
display: flex;
gap: 15px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#controls button {
background: linear-gradient(to right, #ff7e5f, #feb47b);
border: none;
padding: 8px 15px;
border-radius: 20px;
color: white;
cursor: pointer;
font-weight: bold;
transition: all 0.3s ease;
}
#controls button:hover {
transform: scale(1.05);
box-shadow: 0 0 15px rgba(255, 126, 95, 0.5);
}
.particle-count {
position: absolute;
bottom: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>3D Galaxy Animation</h1>
<p>Interactive particle system with 5000 colorful particles rotating in a spiral galaxy pattern.</p>
<p>Move your mouse to tilt the galaxy and explore the cosmic depths.</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div class="particle-count">Particles: 5000</div>
<div id="controls">
<button id="speedUp">Speed Up</button>
<button id="slowDown">Slow Down</button>
<button id="reset">Reset</button>
</div>
</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let speed = 0.5;
let fpsElement = document.getElementById('fps-counter');
let stats = { fps: 0, frames: 0, lastTime: performance.now() };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Setup controls
setupControls();
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
// Create spiral galaxy pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(i / particleCount) * 150;
const angle = i * 0.1 + Math.sin(i * 0.02) * 2;
const height = (Math.sin(i * 0.01) * 50);
// Position
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color - gradient from blue to yellow to red
const colorValue = i / particleCount;
const r = Math.min(1, Math.sin(colorValue * Math.PI) * 2);
const g = Math.min(1, Math.sin(colorValue * Math.PI + 2) * 2);
const b = Math.min(1, Math.sin(colorValue * Math.PI + 4) * 2);
colors[i3] = r;
colors[i3 + 1] = g;
colors[i3 + 2] = b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.0005;
mouseY = (event.clientY - windowHalfY) * 0.0005;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Setup controls
function setupControls() {
document.getElementById('speedUp').addEventListener('click', () => {
speed = Math.min(2, speed + 0.1);
});
document.getElementById('slowDown').addEventListener('click', () => {
speed = Math.max(0.1, speed - 0.1);
});
document.getElementById('reset').addEventListener('click', () => {
speed = 0.5;
});
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Calculate FPS
const now = performance.now()
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an interactive 3D galaxy animation with 5000 particles, mouse tilt response, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff758c);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 126, 179, 0.3);
}
#info p {
margin: 8px 0;
font-size: 0.9rem;
opacity: 0.8;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
text-align: center;
font-size: 0.9rem;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Galaxy Particle Animation</h1>
<p>• 5000 colorful particles</p>
<p>• Spiral galaxy formation</p>
<p>• Mouse tilt interaction</p>
<p>• Starfield background</p>
<p>• Real-time FPS counter</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create the galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 4;
const height = (Math.random() - 0.5) * 100;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) % 1;
color.setHSL(hue, 0.8, 0.5 + Math.random() * 0.3);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 3 + 1;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starCount = 10000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(starCount * 3);
const colors = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const i3 = i * 3;
// Position stars in a spherical distribution
const radius = 1000 + Math.random() * 5000;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positions[i3 + 2] = radius * Math.cos(phi);
// Star colors (mostly white with some blue/amber)
const color = new THREE.Color();
if (Math.random() > 0.7) {
color.setHSL(0.1, 0.3, 0.8 + Math.random() * 0.2); // Blue stars
} else {
color.setHSL(0.12, 0.2, 0.9 + Math.random() * 0.1); // Yellow/white stars
}
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.8
});
const starfield = new THREE.Points(geometry, material);
scene.add(starfield);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// Rotate galaxy
particleSystem.rotation.x = elapsed * 0.05;
particleSystem.rotation.y = elapsed * 0.02;
gemma4:e4b
This is a complete single-file solution using Three.js. It creates a highly optimized and visually impressive interactive particle scene featuring a rotating spiral galaxy, a starfield background, and real-time FPS tracking.
### 🌌 Galactic Particle Animator
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Spiral Galaxy Particles</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: rgba(255, 255, 255, 0.7);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 16px;
pointer-events: none; /* Ensures clicks pass through */
}
</style>
</head>
<body>
<div id="fps-counter">FPS: --</div>
<!-- Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- GLOBAL VARIABLES AND SETUP ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
const numGalaxyParticles = 5000;
const numStarfieldParticles = 20000;
// Mouse tracking for tilt effect
let mouseX = 0;
let mouseY = 0;
// FPS Tracking variables
let frameCount = 0;
let lastTime = performance.now();
function init() {
// 1. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 2. Scene and Camera Setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// Add ambient light (optional but good practice)
scene.add(new THREE.AmbientLight(0x4444aa, 2));
// --- CREATE THE STARFIELD BACKGROUND ---
createStarfield();
// --- CREATE THE GALAXY PARTICLES ---
const galaxyGroup = new THREE.Group();
galaxyParticles = createGalaxy(galaxyGroup);
scene.add(galaxyGroup);
// 3. Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
animate();
}
/**
* Generates a large starfield background using random points in a sphere.
*/
function createStarfield() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < numStarfieldParticles; i++) {
// Random spherical coordinates for distribution
const radius = Math.random() * 800 + 100; // Stars far away
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(Math.random() * 2 - 1);
// Convert to Cartesian coordinates
const x = radius * Math.sin(phi) * Math.cos(theta);
const y = radius * Math.sin(phi) * Math.sin(theta);
const z = radius * Math.cos(phi);
positions.push(x, y, z);
// Assign subtle white/blue color
color.setHSL((i / numStarfieldParticles), 0.7, Math.random() * 0.5 + 0.5);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use colors defined in the buffer geometry
transparent: true,
opacity: 0.8
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
/**
* Generates particles following a spiral pattern (Archimedean/Galactic).
*/
function createGalaxy(group) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < numGalaxyParticles; i++) {
// Parameter 't' controls the distribution along the spiral/depth
const t = Math.random() * 6 * Math.PI; // Full rotation cycles
// Spiral function: radius increases with angle (r = a * theta)
// We use sin(t*k) to keep it contained and make it curl
const r = 10 + (i / numGalaxyParticles) * 40; // Radius expansion
// Z-coordinate controls the depth of the spiral
const z_depth = Math.sin(t * 0.5) * 20;
// X and Y coordinates define the spiral curve
const x = r * Math.cos(t);
const y = r * Math.sin(t) * (1 + (z_depth / 30)); // Slight vertical warp for depth perception
positions.push(x, y, z_depth);
// Assign random vibrant colors to simulate stellar diversity
color.setHSL(Math.random(), 1, Math.random() * 0.4 + 0.5);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use colors defined in the buffer geometry
transparent: true,
opacity: 0.9
});
const points = new THREE.Points(geometry, material);
group.add(points);
return points;
}
/**
* Handles window resizing to keep the canvas full screen.
*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Handles mouse movement to calculate tilt angles.
* @param {MouseEvent} event - The mouse move event object.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX / window.innerWidth) * Math.PI * 2; // Range 0 to 2pi
mouseY = -(event.clientY / window.innerHeight) * Math.PI * 2; // Range 0 to -2pi
}
/**
* The main animation loop.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() / 1000;
// --- 1. Galaxy Rotation (Internal Spiral Movement) ---
// Rotate the entire group slowly around Y axis and apply a subtle wobble
galaxyParticles.rotation.y = time * 0.05 + mouseX * 0.2;
galaxyParticles.rotation.x = Math.sin(time * 0.1) * 0.05;
// --- 2. Starfield Rotation (Deep Space Drift) ---
starfieldParticles.rotation.y += 0.0005;
starfieldParticles.rotation.z -= 0.0003;
// --- 3. Camera Tilt Response (Interactivity) ---
// Smoothly interpolate the camera's rotation based on mouse position
camera.rotation.y += (mouseX * 0.1 - camera.rotation.y) * 0.05;
camera.rotation.x += (mouseY * 0.1 + Math.sin(time * 0.2) * 0.05 - camera.rotation.x) * 0.05;
// --- 4. Render and Update FPS ---
renderer.render(scene, camera);
updateFPS();
}
/**
* Updates the displayed Frames Per Second counter.
*/
function updateFPS() {
const currentTime = performance.now();
const delta = (currentTime - lastTime) / 1000; // Time in seconds
frameCount++;
if (delta >= 0.5) { // Update FPS display every half second
let fps = Math.round(frameCount / delta);
document.getElementById('fps-counter').innerHTML = `FPS: ${fps}`;
// Reset counters
frameCount = 0;
lastTime = currentTime;
}
}
/**
* Initialization call.
*/
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive 3D galaxy animation with 5000 particles that respond to mouse movement, a starfield background, and an FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
margin: 5px 0;
font-size: 0.9rem;
opacity: 0.8;
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
z-index: 100;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-size: 0.9rem;
z-index: 100;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>3D Galaxy Particle Animation</h1>
<p>Interactive spiral galaxy with 5000 particles</p>
<p>Move mouse to tilt the galaxy</p>
</div>
<div id="fps-counter">FPS: 60</div>
<div id="instructions">Move mouse to control galaxy rotation</div>
</div>
<!-- Import Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats;
let particleCount = 5000;
let galaxyRadius = 300;
let galaxyRotationSpeed = 0.001;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000022);
scene.fog = new THREE.Fog(0x000022, 500, 1500);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 3000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add stars background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const material = new THREE.PointsMaterial({
size: 2,
sizeAttenuation: true,
vertexColors: true,
transparent: true,
opacity: 0.9
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
// Create spiral galaxy with particle colors
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.random() * galaxyRadius;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 50;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy-like colors
const color = new THREE.Color();
const hue = (angle / (Math.PI * 2)) + Math.random() * 0.2;
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.5 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Mouse movement handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.01;
mouseY = (event.clientY - windowHalfY) * 0.01;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Rotate galaxy based on mouse position
if (particles) {
particles.rotation.y += mouseX * 0.001;
particles.rotation.x += mouseY * 0.001;
// Add subtle rotation
particles.rotation.y += galaxyRotationSpeed * Math.sin(elapsedTime * 0.5);
}
// Update controls
if (controls) {
controls.update();
}
// Render scene
renderer.render(scene, camera);
// Update FPS counter
updateFPSCounter(delta);
}
// Update FPS counter display
function updateFPSCounter(delta) {
const fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${fps}`;
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this 3D Galaxy Animation:
1. **5000 Colorful Particles**: Created in a spiral galaxy pattern with vibrant, randomly colored particles
2. **Interactive Mouse Control**: Move your mouse to tilt and rotate the galaxy
3. **Starfield Background**: Thousands of stars in the background for depth
4. **FPS Counter**: Real-time performance display in the bottom-right corner
5. **Smooth Animations**:
gemma4:e4b
This is a complex, high-performance visualization that requires careful optimization of Three.js concepts like `BufferGeometry` and managing event handlers efficiently.
Here is the complete single-file HTML implementation:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: 'Arial', sans-serif;
font-size: 16px;
background: rgba(0, 0, 0, 0.5);
padding: 8px 12px;
border-radius: 5px;
user-select: none;
}
</style>
</head>
<body>
<!-- FPS Counter Element -->
<div id="fpsCounter">FPS: 0</div>
<!-- Include Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// ==============================================
// GLOBAL SETUP VARIABLES
// ==============================================
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
// Variables for mouse interaction and tracking
const mouse = new THREE.Vector2();
const targetRotation = new THREE.Euler(0, 0, 0);
const sensitivity = 0.005;
let cameraOffset = new THREE.Vector3(0, 0, 0);
// FPS Tracking variables
let frameCount = 0;
let lastTime = performance.now();
let fpsDisplay;
/**
* Initializes the Three.js scene components (Scene, Camera, Renderer).
*/
function init() {
// Scene setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Initial camera position
camera.position.z = 5;
// --- Create Particle Systems ---
createGalaxyParticles(5000);
createStarField(10000);
// --- Event Listeners ---
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove, false);
// Start the animation loop
animate();
}
/**
* Generates the main spiral galaxy particle system.
* @param {number} count - Number of particles to create.
*/
function createGalaxyParticles(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Galaxy parameters (Spiral effect)
const maxRadius = 50;
const spiralFactor = 0.8; // Controls how tightly the arms wrap
const baseMagnitude = 100;
for (let i = 0; i < count; i++) {
// Calculate angle and radius for a spiral pattern
const theta = Math.random() * Math.PI * 2;
// Spiral formula: r = a * theta + b
const radius = maxRadius + spiralFactor * theta;
// Add slight randomness to the magnitude (depth/z-axis)
const z = baseMagnitude * (Math.random() - 0.5);
// Position data: X, Y, Z
positions.push(radius * Math.cos(theta)); // X
positions.push(Math.random() * maxRadius * 1.5); // Y (vertical spread)
positions.push(z + radius * Math.sin(theta) * 0.2); // Z
// Assign random color
const color = new THREE.Color();
color.setHSL(Math.random(), 1, Math.random() * 0.5 + 0.3);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup: PointsMaterial is efficient for basic particles
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors stored in the geometry
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Generates a distant starfield background using many small particles.
* @param {number} count - Number of stars to create.
*/
function createStarField(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < count; i++) {
// Place stars far away in a large box
positions.push(Math.random() * 400 - 200); // X
positions.push(Math.random() * 400 - 200); // Y
positions.push(Math.random() * 400 - 200); // Z
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Use a material that gives the illusion of distance/brightness
const material = new THREE.PointsMaterial({
size: 1.5,
color: 0xaaaaaa,
transparent: true,
opacity: 0.6
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
/**
* Handles window resizing to keep the canvas fit.
*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Handles mouse movement to translate into camera/scene rotation (tilt).
* @param {Event} event - The mouse move event.
*/
function onDocumentMouseMove(event) {
// Normalize coordinates (-1 to +1)
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
/**
* The main animation loop function.
*/
function animate(time) {
requestAnimationFrame(animate);
// --- Time-based rotation and movement ---
const timeFactor = performance.now() * 0.0005;
const speed = 0.001;
// 1. Galaxy Rotation (Self-rotation of the particles)
galaxyParticles.rotation.y += speed * 0.1;
galaxyParticles.rotation.x += speed * 0.05;
// 2. Starfield Movement (Simulating a slow drift/parallax)
starFieldParticles.position.y = Math.sin(timeFactor * 0.1) * 10;
starFieldParticles.rotation.y += speed * 0.001;
// --- Interactive Camera Update (Tilt Effect) ---
// Smoothly calculate the desired camera rotation based on mouse input
targetRotation.set(mouse.x * sensitivity, Math.PI / 2 - mouse.y * sensitivity, 0);
// Lerp current camera rotation towards target rotation for smoothness
camera.rotation.slerp(targetRotation, 0.05);
// --- Rendering ---
renderer.render(scene, camera);
// Update FPS counter
updateFPS();
}
/**
* Calculates and displays the current Frames Per Second (FPS).
*/
function updateFPS() {
const currentTime = performance.now();
frameCount++;
const deltaTime = currentTime - lastTime;
if (deltaTime >= 1000) { // Update every second
let fps = Math.round(frameCount * 1000 / deltaTime);
document.getElementById('fpsCounter').textContent = `FPS: ${fps}`;
// Reset counters for the next second calculation
frameCount = 0;
lastTime = currentTime;
}
}
// Start everything up!
init();
</script>
</body>
</html>
```
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive 3D galaxy animation with 5000 particles that respond to mouse movement, a starfield background, and an FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
margin: 5px 0;
font-size: 1rem;
opacity: 0.8;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
font-family: monospace;
font-size: 1.2rem;
}
#instructions {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 12px 25px;
border-radius: 30px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
text-align: center;
font-size: 1rem;
opacity: 0.8;
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>5,000 particles in a spiral galaxy</p>
<p>Move mouse to tilt the view</p>
</div>
<div id="fps-counter">FPS: 60</div>
<div id="instructions">Move your mouse to interact with the galaxy</div>
</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 60 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 50, 200);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 150;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.2,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create spiral galaxy
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral parameters
const radius = Math.sqrt(Math.random()) * 50;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 10;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color based on position and time
const hue = (angle / (Math.PI * 2)) * 0.5 + 0.5;
const color = new THREE.Color().setHSL(hue, 1, 0.5);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random size
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const material = new THREE.PointsMaterial({
size: 1,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Rotate particles
if (particleSystem) {
particleSystem.rotation.y += 0.001;
// Mouse tilt effect
camera.position.x += (mouseX * 50 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 50 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
// Update FPS counter
stats.fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${stats.fps}`;
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this Interactive Galaxy Animation:
1. **5,000 Colorful Particles**: Created in a spiral galaxy pattern with vibrant colors that shift across the spectrum
2. **Mouse Interaction**: The galaxy tilts and rotates based on mouse movement for an immersive experience
3. **Starfield Background**: 10,000 stars scattered throughout space for depth
4. **FPS Counter**: Displays real-time frames p
gemma4:e4b
This is a highly intensive and visually demanding task that requires advanced use of WebGL concepts (via Three.js). The resulting code is contained within a single HTML file for easy execution.
Due to browser security restrictions, the performance will depend on your machine's CPU/GPU. For 5000 particles, modern browsers should handle it smoothly.
### Interactive Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000011; }
canvas { display: block; }
#fpsCounter {
position: absolute;
top: 20px;
left: 20px;
font-family: 'Arial', sans-serif;
color: #ffffff;
background-color: rgba(0, 0, 0, 0.5);
padding: 10px 20px;
border-radius: 8px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fpsCounter">FPS: 0</div>
<!-- Import Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables and Setup ---
let scene, camera, renderer;
let particles, galaxyParticles;
const particleCount = 5000;
let mouseX = 0;
let mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
// FPS Tracking Variables
let frameCount = 0;
let lastTime = performance.now();
const fpsDisplay = document.getElementById('fpsCounter');
function init() {
// 1. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 2. Scene and Camera Setup
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// --- 3. Particle System Creation (The Galaxy) ---
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < particleCount; i++) {
// We use a spiral curve formula for the galaxy effect:
// R = radius based on index, Z = depth/distance
// Theta = angle, adjusted to make it look like a flat disk.
const u = (i / particleCount) * Math.PI * 4; // Angle multiplier (full rotation)
const r = Math.sqrt(Math.random()) * 30 + 5; // Base radius (spread)
const zPos = Math.sin(u * 1.5) * 20; // Z position (depth/spiral curvature)
const xPos = r * Math.cos(u);
const yPos = r * Math.sin(u) + (Math.random() - 0.5) * 2; // Slight vertical jitter
positions.push(xPos, yPos, zPos);
// Assign random colors for a colorful effect
color.setHSL((i / particleCount) + 0.5, 1, Math.random());
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Particle Material (using vertex colors)
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Crucial for using the assigned colors
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
// --- 4. Starfield Background (Simple Cube of Points) ---
const starGeometry = new THREE.SphereGeometry(100, 32, 32); // Use a large sphere/box for background stars
const starMaterial = new THREE.PointsMaterial({
size: 0.5,
color: 0xaaaaaa,
transparent: true,
opacity: 0.6
});
// Since we are simulating a field, let's generate more points for the background
const starPositions = [];
for (let i = 0; i < 50000; i++) {
starPositions.push(
(Math.random() - 0.5) * 200,
(Math.random() - 0.5) * 200,
(Math.random() - 0.5) * 200
);
}
const starGeometry = new THREE.BufferGeometry();
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
const starParticles = new THREE.Points(starGeometry, starMaterial);
scene.add(starParticles);
// --- 5. Event Listeners and Initial Setup ---
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
animate();
}
function onWindowResize() {
camera.viewport = new THREE.Vector2(0, 0); // Reset viewport
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
// Normalize mouse coordinates to a range like [-1, 1]
mouseX = (event.clientX - windowHalfX) / windowHalfX;
mouseY = (event.clientY - windowHalfY) / windowHalfY;
}
// --- Animation Loop ---
function animate() {
requestAnimationFrame(animate);
const currentTime = performance.now();
const deltaTime = currentTime - lastTime;
// 1. Update FPS Counter
frameCount++;
if (deltaTime >= 1000) { // Update every second
const fps = Math.round(1000 / deltaTime);
fpsDisplay.textContent = `FPS: ${fps}`;
lastTime = currentTime;
frameCount = 0;
}
// 2. Camera Movement (Mouse Interaction - Tilt)
// Apply gentle movement based on mouse position
camera.position.x += (mouseX * 10 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 10 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// 3. Particle Animation (Rotation and Movement)
const time = Date.now() * 0.0001;
const rotationSpeed = 0.0002;
// Galaxy Rotation
galaxyParticles.rotation.y += rotationSpeed;
galaxyParticles.rotation.x += 0.00005;
// Starfield Subtle Movement (Parallax effect)
scene.getObjectByName('star-background').rotation.z += 0.0001;
// 4. Render Scene
renderer.render(scene, camera);
}
// Start the application
init();
</script>
</body>
</html>
```
gemma4:12b-q4_K_M
This is a complete, single-file solution. It uses **Three.js** for the 3D engine and **BufferGeometry** to ensure that rendering 5,000 particles remains smooth (60 FPS) by offloading the heavy lifting to the GPU.
I have implemented a "Logarithmic Spiral" algorithm to create the galaxy shape, added a mouse-parallax effect, and included a real-time FPS tracker.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle System</title>
<style>
body {
margin: 0;
padding: 0;
overflow: hidden;
background-color: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
canvas {
display: block;
}
#ui-layer {
position: absolute;
top: 20px;
left: 20px;
color: white;
pointer-events: none;
text-shadow: 0 0 5px rgba(0,0,0,0.8);
}
#fps-counter {
font-family: monospace;
font-size: 14px;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.2);
}
.instructions {
position: absolute;
bottom: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.4);
font-size: 12px;
letter-spacing: 1px;
}
</style>
</head>
<body>
<div id="ui-layer">
<div id="fps-counter">FPS: 60</div>
</div>
<div class="instructions">MOVE MOUSE TO TILT • SCROLL TO ZOOM</div>
<!-- Load Three.js from CDN -->
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.160.0/build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
// --- Configuration ---
const PARTICLE_COUNT = 5000;
const SPIRAL_ARMS = 3;
const COLORS = [0xff6384, 0x36a2eb, 0xffce56, 0x9966ff, 0x00ff88];
// --- Variables ---
let scene, camera, renderer, particles;
let mouseX = 0, mouseY = 0;
let targetX = 0, targetY = 0;
let frameCount = 0;
let lastTime = performance.now();
const fpsDisplay = document.getElementById('fps-counter');
init();
animate();
function init() {
// Scene & Camera
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 400;
// Renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// Galaxy Geometry (BufferGeometry for performance)
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(PARTICLE_COUNT * 3);
const colors = new Float32Array(PARTICLE_COUNT * 3);
for (let i = 0; i < PARTICLE_COUNT; i++) {
// Spiral Math: r = a * e^(b*theta)
const angle = Math.random() * Math.PI * 2;
const dist = (Math.pow(Math.random(), 0.5) * 300) + 20; // Spread out radius
// Create spiral arms effect
const armOffset = (i % SPIRAL_ARMS) * ((Math.PI * 2) / SPIRAL_ARMS);
const finalAngle = angle + armOffset;
// Position calculations
positions[i * 3] = Math.cos(finalAngle) * dist + (Math.random() - 0.5) * 20; // X
positions[i * 3 + 1] = (Math.random() - 0.5) * 40; // Y (thickness)
positions[i * 3 + 2] = Math.sin(finalAngle) * dist + (Math.random() - 0.5) * 20; // Z
// Colors
const color = new THREE.Color(COLORS[Math.floor(Math.random() * COLORS.length)]);
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
// Material
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.8,
blending: THREE.AdditiveBlending // Makes it look "glowy"
});
particles = new THREE.Points(geometry, material);
scene.add(particles);
// Background Starfield (Static)
const starGeo = new THREE.BufferGeometry();
const starPos = new Float32Array(10000 * 3);
for(let i=0; i<30000; i++) {
starPos[i] = (Math.random() - 0.5) * 2000;
}
starGeo.setAttribute('position', new THREE.BufferAttribute(starPos, 3));
const starMat = new THREE.PointsMaterial({ size: 0.7, color: 0xffffff });
const stars = new THREE.Points(starGeo, starMat);
scene.add(stars);
// Listeners
window.addEventListener('resize', onWindowResize);
window.addEventListener('mousemove', (e) => {
targetX = (e.clientX - window.innerWidth / 2) * 0.05;
targetY = (e.clientY - window.innerHeight / 2) * 0.05;
});
// Zoom Control
window.addEventListener('wheel', (e) => {
camera.position.z += e.deltaY * 0.1;
camera.position.z = Math.max(50, Math.min(1000, camera.position.z));
});
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
// Smooth Mouse Interpolation (Lerp)
mouseX += (targetX - mouseX) * 0.05;
mouseY += (targetY - mouseY) * 0.05;
// Rotate the Galaxy
particles.rotation.y += 0.002;
particles.rotation.x = mouseY * 0.1;
particles.rotation.z = mouseX * 0.1;
// FPS Counter Logic
frameCount++;
const time = performance.now();
if (time >= lastTime + 1000) {
fpsDisplay.innerText = `FPS: ${frameCount}`;
frameCount = 0;
lastTime = time;
}
renderer.render(scene, camera);
}
</script>
</body>
</html>
```
### Key Features of this Implementation:
1. **Performance:** Uses `THREE.BufferGeometry` and `THREE.Points`. This is the professional way to handle thousands of particles because it sends a single array of data to the GPU rather than creating 5,000 individual objects.
2. **Visual Style:** Used `THREE.AdditiveBlending`, which causes overlapping particles to "brighten" each other, mimicking the look of real stars and nebulae.
3. **Spiral Logic:** Instead of a random cloud, I used polar coordinates ($x = \cos(\theta) \cdot r$) with an added arm offset to create that distinct galaxy spiral shape.
4. **Interactivity:**
* **Tilt:** The galaxy tilts based on your mouse position using linear interpolation (Lerp) for a smooth, "weighty" feel.
* **Zoom:** Use your scroll wheel to move the camera closer or further away.
5. **Optimization:** Includes an FPS counter and handles window resizing automatically to maintain the correct aspect ratio.
gemma4:e4b
This solution creates a highly detailed, single-file HTML page. It uses Three.js to render a massive particle system forming a spiral galaxy, adds a static starfield background, and implements mouse-based rotation for interactivity, all while tracking the FPS.
### Single File HTML Implementation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Spiral Galaxy Particle Field</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000000;
}
canvas {
display: block;
}
#fps-counter {
position: absolute;
top: 20px;
left: 20px;
color: #ffffff;
font-family: 'Arial', sans-serif;
font-size: 18px;
background: rgba(0, 0, 0, 0.5);
padding: 8px 15px;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starParticles;
const particleCount = 5000;
let mouseX = 0;
let mouseY = 0;
// --- Initialization ---
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
// 2. Camera Setup
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 100;
// 3. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. Create Components
createGalaxy();
createStarfield();
// 5. Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onMouseMove);
// Start the animation loop
animate();
}
/**
* Creates the spiral galaxy particle system.
* Uses parametric equations for a spiral shape.
*/
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < particleCount; i++) {
// Calculate radius (r) and angle (theta) based on index for spiral effect
const t = i / particleCount;
// Spiral formula: Radius increases with t, angle increases with t
const r = 5 + (t * 150);
const theta = t * Math.PI * 6; // 6 full rotations
const z = Math.sin(t * 3) * 50; // Depth variation
// Convert polar to Cartesian coordinates
const x = r * Math.cos(theta);
const y = r * Math.sin(theta);
const z_pos = z;
positions.push(x, y, z_pos);
// Color gradient: Map index to color (e.g., blue to red/yellow)
color.setHSL(t * 0.6, 1.0, 0.5);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Use PointsMaterial for rendering particles
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true, // Use the colors set in the geometry
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a dense, static starfield background.
*/
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starPositions = [];
const starColors = [];
const starCount = 20000;
for (let i = 0; i < starCount; i++) {
// Random positions in a large cube
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starPositions.push(x, y, z);
// White/light blue color for stars
starColors.push(1, 1, 1);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
starGeometry.setAttribute('color', new THREE.Float32BufferAttribute(starColors, 3));
const starMaterial = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
sizeAttenuation: true
});
starParticles = new THREE.Points(starGeometry, starMaterial);
scene.add(starParticles);
}
// --- Event Handlers ---
function onWindowResize() {
camera.viewport.setSize(window.innerWidth, window.innerHeight);
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onMouseMove(event) {
// Normalize mouse coordinates to range [-1, 1]
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
// --- Animation Loop & Logic ---
let lastTime = 0;
let frameCount = 0;
let fpsStartTime = performance.now();
function animate(time) {
requestAnimationFrame(animate);
// 1. Calculate FPS
frameCount++;
const elapsed = performance.now() - fpsStartTime;
if (elapsed >= 1000) {
const fps = Math.round(frameCount * 1000 / elapsed);
document.getElementById('fps-counter').textContent = `FPS: ${fps}`;
frameCount = 0;
fpsStartTime = performance.now();
}
// 2. Galaxy Rotation (Constant slow rotation)
const timeFactor = time * 0.0001;
galaxyParticles.rotation.y += 0.001;
galaxyParticles.rotation.x += 0.0005;
// 3. Starfield Rotation (Subtle slow rotation)
starParticles.rotation.y += 0.0001;
// 4. Mouse Interaction (Tilt)
// Apply mouse movement to the camera/scene rotation
camera.position.x = mouseX * 5;
camera.position.y = mouseY * 5;
camera.lookAt(scene.position);
// 5. Render
renderer.render(scene, camera);
}
// Start the application
init();
</script>
</body>
</html>
```
### Key Features Explained:
1. **Particle Geometry (Spiral):**
* The `createGalaxy` function does not use random points. Instead, it calculates the position of each particle (`i`) using mathematical formulas derived from polar coordinates ($\text{radius} = r(\text{index})$, $\text{angle} = \theta(\text{index})$).
* This forces the points into a continuous, spiral, galaxy-like structure.
* **Color Gradient:** The particle color is mapped based on its index (`t = i / particleCount`), creating a smooth color transition across the galaxy.
2. **Interactivity (Mouse Tilt):**
* The `onMouseMove` listener captures the mouse position.
* In the `animate` loop, the camera's position is slightly adjusted using `mouseX` and `mouseY`. This simulates "tilting" the camera towards the cursor, giving the feeling of interacting with the 3D space.
3. **Starfield Background:**
* `createStarfield` generates 20,000 particles with completely random coordinates spanning a large volume.
* These particles are given a separate, slow rotation (`starParticles.rotation.y += 0.0001;`) to create a sense of cosmic depth and movement.
4. **Performance (FPS Counter):**
* A basic timing mechanism using `performance.now()` tracks the elapsed time over a short interval (1 second) to accurately calculate and display the current Frames Per Second (FPS).
5. **Smooth Animation:**
* The animation uses `requestAnimationFrame`, which is the standard, highly efficient way to run smooth, browser-optimized animations in JavaScript.
* The rotations are applied incrementally (`+= 0.001`), ensuring constant, smooth motion.
deepseek-coder-v2:16b
Sure! Below is an example of an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN. This code will create a galaxy-like spiral with 5000 colorful particles that respond to mouse movement and have a starfield background with an FPS counter in the corner.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fps { position: absolute; top: 10px; left: 10px; color: white; font-family: monospace; }
</style>
</head>
<body>
<div id="fps">FPS: -</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Particle system setup
const particleCount = 5000;
const particles = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
particles[i * 3] = (Math.random() - 0.5) * 20;
particles[i * 3 + 1] = (Math.random() - 0.5) * 20;
particles[i * 3 + 2] = (Math.random() - 0.5) * 20;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.Float32BufferAttribute(particles, 3));
const material = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1 });
const pointCloud = new THREE.Points(geometry, material);
scene.add(pointCloud);
// Starfield background
const starCount = 2000;
const stars = [];
for (let i = 0; i < starCount; i++) {
const s = new THREE.Vector3();
s.x = THREE.MathUtils.randFloatSpread(200);
s.y = THREE.MathUtils.randFloatSpread(200);
s.z = THREE.MathUtils.randFloatSpread(200);
stars.push(s);
}
const starGeometry = new THREE.BufferGeometry();
const starPositions = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
starPositions[i * 3] = stars[i].x;
starPositions[i * 3 + 1] = stars[i].y;
starPositions[i * 3 + 2] = stars[i].z;
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
const starMaterial = new THREE.PointsMaterial({ color: 0x1e1e1e, size: 0.5 });
const starField = new THREE.Points(starGeometry, starMaterial);
scene.add(starField);
// Camera position and mouse movement response
camera.position.z = 40;
let mouseX = 0, mouseY = 0;
window.addEventListener('mousemove', (event) => {
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
});
function animate() {
requestAnimationFrame(animate);
// Update camera position based on mouse movement
const rotationSpeed = 0.01;
camera.position.x += (mouseX * rotationSpeed);
camera.position.y += (mouseY * rotationSpeed);
// Rotate the particles to create a spiral effect
pointCloud.rotation.z += 0.005;
pointCloud.rotation.y += 0.005;
renderer.render(scene, camera);
}
let fps = 0;
const startTime = Date.now();
function updateFPS() {
const currentTime = Date.now();
if (currentTime - startTime >= 1000) {
document.getElementById('fps').innerText = `FPS: ${fps}`;
fps = 0;
startTime = currentTime;
}
fps++;
}
animate();
setInterval(updateFPS, 100);
</script>
</body>
</html>
```
This code will create a smooth and visually impressive 3D particle animation with a starfield background. The particles rotate in a spiral motion based on mouse movement, and an FPS counter is displayed in the corner of the screen.
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy animation with 5000 colorful particles that respond to mouse movement, a starfield background, and an FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
cursor: pointer;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 20px;
width: 100%;
text-align: center;
color: rgba(255, 255, 255, 0.8);
font-size: 28px;
font-weight: 300;
letter-spacing: 3px;
text-transform: uppercase;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="title">Galaxy Particle Animation</div>
<div id="info">Interactive 3D Galaxy with 5000 Particles</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move mouse to tilt the galaxy</div>
</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats = { fps: 0, frameCount: 0, lastTime: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Add orbit controls for manual rotation
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// Start animation
animate();
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create particles in a spiral galaxy pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral galaxy formation
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 50;
// Position particles in spiral
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy colors
const color = new THREE.Color();
const hue = (Math.random() * 0.3 + 0.5); // Blue to purple
const saturation = 0.8;
const lightness = 0.5 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random particle sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
// Create particle system
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.0005;
mouseY = (event.clientY - windowHalfY) * 0.0005;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update FPS counter
updateFPS();
// Rotate galaxy based on mouse position
if (particles) {
particles.rotation.y += 0.001 + mouseX * 0.005;
particles.rotation.x = mouseY * 0.2;
}
// Update controls
if (controls) {
controls.update();
}
// Render scene
renderer.render(scene, camera);
}
// Update FPS counter
function updateFPS() {
const delta = clock.getDelta();
stats.frameCount++;
if (stats.lastTime + 1 < performance.now()) {
stats.fps = stats.frameCount;
stats.frameCount = 0;
stats.lastTime = performance.now();
document.getElementById('fps-counter').textContent = `FPS: ${stats.fps}`;
}
}
// Initialize the application
init();
</script>
</body>
</html>
```
## Features of this Galaxy Animation:
1. **5000 Colorful Particles**: Created in a realistic spiral galaxy pattern with varying colors and sizes
2. **Interactive Mouse Control**: The galaxy tilts based on mouse movement
3. **Starfield Background**: Thousands of stars create a deep space environment
4. **FPS Counter**: Displays real-time fram
gemma4:e4b
This is a complex, resource-intensive animation that requires modern JavaScript and the Three.js library. The following single HTML file contains all the necessary structure, styling, and logic to achieve the desired interactive, galaxy-like particle animation.
### Interactive Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive 3D Galaxy Particle Field</title>
<style>
/* Global reset and full screen setup */
body {
margin: 0;
overflow: hidden;
background-color: #000000;
}
canvas {
display: block;
}
/* Overlay for FPS Counter */
#fps-counter {
position: fixed;
top: 10px;
left: 10px;
color: #ffffff;
font-family: 'Courier New', Courier, monospace;
font-size: 16px;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<!-- FPS Counter Element -->
<div id="fps-counter">FPS: 0</div>
<!-- Three.js Library CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let particles, particleGeometry, particleMaterial;
const NUM_PARTICLES = 5000;
// Interaction state
const mouse = new THREE.Vector2();
const targetRotation = { x: 0, y: 0 };
// FPS Tracking Variables
let frameCount = 0;
let lastTime = performance.now();
let fpsUpdateInterval = 0.5; // Update FPS counter every half second
// --- Initialization Function ---
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x000000, 1, 500);
// 2. Camera Setup
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 3. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. Create Particles (The Galaxy)
createParticleSystem();
// 5. Create Starfield Background
createStarfield();
// 6. Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onMouseMove, false);
// Start the animation loop
animate();
}
/**
* Creates the main particle system arranged in a spiral galaxy shape.
*/
function createParticleSystem() {
// Use BufferGeometry for performance
particleGeometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < NUM_PARTICLES; i++) {
// Calculate position using a spiral equation (polar coordinates)
const t = (i / NUM_PARTICLES) * Math.PI * 4; // Controls the number of rotations
const r = Math.sqrt(i / NUM_PARTICLES) * 50; // Radius increases with index
// X = r * cos(t), Y = r * sin(t), Z = z_offset
const x = r * Math.cos(t) * Math.cos(0.5);
const y = r * Math.sin(t) * Math.sin(0.5);
const z = Math.sqrt(r * r - (x * x + y * y)) * 0.5;
positions.push(x, y, z);
// Assign random but related colors for a nebula effect
color.setHSL(i / NUM_PARTICLES, 1.0, 0.5 + Math.random() * 0.3);
colors.push(color.r, color.g, color.b);
}
particleGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Particle Material (Using PointsMaterial for simple, colorful dots)
particleMaterial = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors set in the geometry
transparent: true,
blending: THREE.AdditiveBlending // Makes particles glow when overlapping
});
particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
}
/**
* Creates a simple, distant starfield background using Points.
*/
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starVertices = [];
// Generate 10,000 random stars in a large cube
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 1000;
const y = (Math.random() - 0.5) * 1000;
const z = (Math.random() - 0.5) * 1000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1,
transparent: true,
blending: THREE.AdditiveBlending
});
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
/**
* Handles window resizing to keep the canvas full screen.
*/
function onWindowResize() {
camera.viewport = { x: 0, y: 0, width: 1, height: 1 };
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Updates the target rotation based on mouse movement.
* @param {MouseEvent} event
*/
function onMouseMove(event) {
// Normalize mouse coordinates (-1 to +1)
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
// Smoothly update the target rotation (tilt effect)
targetRotation.y += (mouse.x * 0.01 - targetRotation.y) * 0.05;
targetRotation.x += (mouse.y * 0.01 - targetRotation.x) * 0.05;
}
/**
* Main animation loop.
* @param {number} time - Current timestamp.
*/
function animate(time) {
requestAnimationFrame(animate);
const delta = (time - lastTime) / 1000; // Time elapsed since last frame (in seconds)
lastTime = time;
// 1. Update Particle Rotation (Galaxy Spin)
// Rotate the particles around the Y-axis slowly
particles.rotation.y += 0.0005;
// 2. Apply Mouse Interaction (Tilt)
// Smoothly interpolate the camera/scene rotation towards the mouse targets
camera.rotation.y += (targetRotation.y - camera.rotation.y) * 0.05;
camera.rotation.x += (targetRotation.x - camera.rotation.x) * 0.05;
// 3. Starfield movement (Subtle parallax effect)
// Rotate the stars slightly to simulate depth/movement
scene.getObjectByName("stars")?.rotation.y += 0.00005;
// 4. Render
renderer.render(scene, camera);
// 5. Update FPS Counter
frameCount++;
const elapsed = (performance.now() - lastTime) / 1000;
if (elapsed >= fpsUpdateInterval) {
const fps = Math.round(frameCount / elapsed);
document.getElementById('fps-counter').innerText = `FPS: ${fps}`;
frameCount = 0;
lastTime = performance.now();
}
}
// --- Execution ---
init();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN, you can follow the steps below. This example will include a starfield background, 5000 colorful particles rotating in a galaxy-like spiral, and a responsive design that tilts based on mouse movement. Additionally, it will display an FPS (frames per second) counter in the corner.
Here's how you can set up your HTML file:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fps { position: absolute; top: 10px; left: 10px; color: white; }
</style>
</head>
<body>
<div id="fps">FPS: ?</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create particles
const geometry = new THREE.BufferGeometry();
const material = new THREE.PointsMaterial({ color: 0x888888, size: 0.1 });
const count = 5000;
const positions = new Float32Array(count * 3);
for (let i = 0; i < count * 3; i++) {
positions[i] = (Math.random() - 0.5) * 10;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const pointCloud = new THREE.Points(geometry, material);
scene.add(pointCloud);
// Background starfield
const starsGeometry = new THREE.BufferGeometry();
const starPositions = [];
for (let i = 0; i < count; i++) {
const x = -150 + Math.random() * 300;
const y = -150 + Math.random() * 300;
const z = -150 + Math.random() * 300;
starPositions.push(x, y, z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
const starMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
const starField = new THREE.Points(starsGeometry, starMaterial);
scene.add(starField);
// Camera position and rotation
camera.position.z = 5;
// Mouse movement response for tilt effect
let mouseX = 0, mouseY = 0;
window.addEventListener('mousemove', (event) => {
mouseX = event.clientX - window.innerWidth / 2;
mouseY = event.clientY - window.innerHeight / 2;
});
// Animation loop
function animate() {
requestAnimationFrame(animate);
const tiltAngleX = mouseY / 100;
const tiltAngleY = mouseX / 100;
camera.rotation.x = tiltAngleX;
camera.rotation.y = tiltAngleY;
renderer.render(scene, camera);
}
animate();
// FPS counter
let fpsCounter = 0;
let lastTime = performance.now();
function updateFPS() {
const now = performance.now();
const delta = now - lastTime;
if (delta >= 1000) {
document.getElementById('fps').textContent = `FPS: ${fpsCounter}`;
fpsCounter = 0;
lastTime = now;
} else {
fpsCounter++;
}
requestAnimationFrame(updateFPS);
}
updateFPS();
</script>
</body>
</html>
```
This code sets up a basic Three.js scene with 5000 particles and a starfield background. The camera responds to mouse movement by tilting, and an FPS counter is displayed in the corner of the canvas. You can run this HTML file directly in any modern web browser.
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy simulation with 5000 colorful particles, responsive to mouse movement, and a starfield background - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Simulation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
max-width: 300px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
font-size: 0.9rem;
line-height: 1.5;
margin-bottom: 15px;
}
#info ul {
padding-left: 20px;
margin-bottom: 15px;
}
#info li {
margin-bottom: 8px;
font-size: 0.9rem;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
font-size: 1.2rem;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
text-align: center;
font-size: 0.9rem;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>Experience a galaxy simulation with 5000 colorful particles rotating in a spiral pattern.</p>
<ul>
<li>Move your mouse to tilt the galaxy</li>
<li>Particles respond to your cursor movement</li>
<li>Starfield background for immersive experience</li>
<li>Real-time FPS counter</li>
</ul>
<p>Each particle is a unique color with varying size and speed</p>
</div>
<div id="fps-counter">FPS: 60</div>
<div id="instructions">Move your mouse to interact with the galaxy</div>
</div>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats = { fps: 60, lastFpsUpdate: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add orbit controls for camera movement
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy particles
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral galaxy pattern
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 40;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color variations
const color = new THREE.Color();
const hue = (i / particleCount) * 0.5 + 0.5; // Blue to purple
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.4;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Vary particle sizes
sizes[i] = Math.random() * 3 + 1;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Mouse movement handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.0005;
mouseY = (event.clientY - windowHalfY) * 0.0005;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update FPS counter
updateFPS();
// Rotate particles
const time = clock.getElapsedTime();
particles.rotation.x = time * 0.05;
particles.rotation.y = time * 0.02;
// Mouse interaction
camera.position.x += (mouseX * 100 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 100 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
}
// Update FPS counter
function updateFPS() {
const now = pe
gemma4:e4b
This is a complex, highly visual, and performance-intensive script. It combines geometry calculation, advanced rendering techniques (like particle systems), and real-time performance monitoring into a single file.
Here is the complete, self-contained HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Galaxy Particle Field</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000000;
}
canvas {
display: block;
}
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: rgba(255, 255, 255, 0.7);
font-family: 'Courier New', monospace;
padding: 5px 10px;
background-color: rgba(0, 0, 0, 0.5);
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- GLOBAL VARIABLES ---
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
// --- PERFORMANCE TRACKING ---
let frameCount = 0;
let lastTime = performance.now();
const fpsCounterElement = document.getElementById('fps-counter');
// --- INITIALIZATION FUNCTIONS ---
/**
* Sets up the core Three.js environment (Scene, Camera, Renderer).
*/
function initScene() {
// Scene setup
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000000, 0.0005); // Subtle depth effect
// Camera setup
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 150;
// Renderer setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Create the components
createGalaxyParticles(5000);
createStarField(10000);
}
/**
* Creates the main galaxy spiral particle system.
* Uses a parametric function (spiral) to position the points.
* @param {number} count - Number of particles.
*/
function createGalaxyParticles(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
const radiusScale = 10; // Controls how spread out the galaxy is
const spiralFactor = 0.05; // Controls the tightness of the spiral
for (let i = 0; i < count; i++) {
// 1. Calculate spiral position (r, theta, z)
const t = i / count * Math.PI * 6; // Angle based on index
const r = Math.sin(t * spiralFactor) * radiusScale * (1 + i / count * 0.5);
const z = Math.cos(t * spiralFactor) * radiusScale * (1 + i / count * 0.5);
const x = r;
const y = z * 0.5; // Flatten the galaxy slightly on the Y-axis
// 2. Store positions
positions.push(x, y, z);
// 3. Calculate color based on position/index for a colorful effect
const hue = (i / count) * 0.8 + 0.2; // Gradient of colors
color.setHSL(hue, 1.0, 0.5);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup
const material = new THREE.PointsMaterial({
size: 2,
sizeAttenuation: true,
transparent: true,
opacity: 0.8,
vertexColors: true // Use the colors stored in the geometry
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a distant, static starfield background.
* @param {number} count - Number of stars.
*/
function createStarField(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < count; i++) {
// Random positions far away
const x = (Math.random() - 0.5) * 4000;
const y = (Math.random() - 0.5) * 4000;
const z = (Math.random() - 0.5) * 4000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
size: 1,
color: 0xaaaaee,
sizeAttenuation: true,
transparent: true,
opacity: 0.8
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
// --- INTERACTIVITY HANDLERS ---
/**
* Updates mouse coordinates used for camera tilt.
* @param {Event} event - Mouse move event.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.5;
mouseY = (event.clientY - windowHalfY) * 0.5;
}
/**
* Handles window resizing to keep the renderer responsive.
*/
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.viewport = new THREE.Vector2(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// --- ANIMATION LOOP & LOGIC ---
/**
* Main animation loop using requestAnimationFrame.
* @param {number} time - Current time provided by the browser.
*/
function animate(time) {
requestAnimationFrame(animate);
// 1. Time-based rotation (Galaxy movement)
const timeFactor = time * 0.0005;
// Rotate the galaxy slightly around the Y-axis
galaxyParticles.rotation.y += 0.001;
// Simulate a slow, overall orbit/rotation for the entire scene
scene.rotation.y = timeFactor * 0.1;
// 2. Mouse Interaction (Camera Tilt)
// Smoothly interpolate the camera position based on mouse movement
camera.position.x += (mouseX * 0.1 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 0.1 - camera.position.y) * 0.05;
camera.lookAt(scene.position); // Always look at the center
// 3. Starfield Animation (Subtle movement)
// Makes the distant stars seem to flow or pulse slightly
starFieldParticles.rotation.y += 0.00005;
// 4. Render the scene
renderer.render(scene, camera);
// 5. Update FPS Counter
updateFPS(time);
}
/**
* Calculates and displays the current FPS.
* @param {number} time - Current time.
*/
function updateFPS(time) {
frameCount++;
const elapsed = time - lastTime;
// Calculate FPS every 200ms for smoother display
if (elapsed >= 200) {
const fps = Math.round(1000 / (elapsed / frameCount));
fpsCounterElement.textContent = `FPS: ${fps}`;
// Reset counters
frameCount = 0;
lastTime = time;
}
}
// --- EXECUTION ---
try {
initScene();
animate(performance.now());
} catch (e) {
console.error("An error occurred during initialization:", e);
}
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from the CDN, you can follow the steps below to set up your project. This example will include a starfield background, colorful particles rotating in a spiral galaxy-like motion, and a responsive design that reacts to mouse movement for tilting effects. Additionally, it will display an FPS (Frames Per Second) counter in the corner of the screen.
Here's how you can structure your HTML file:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fps { position: absolute; top: 10px; left: 10px; color: white; }
</style>
</head>
<body>
<div id="fps">FPS: -</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Stars (background)
const starsGeometry = new THREE.BufferGeometry();
const starVertices = [];
for (let i = 0; i < 5000; i++) {
const x = -1000 + Math.random() * 2000;
const y = -1000 + Math.random() * 2000;
const z = -1000 + Math.random() * 2000;
starVertices.push(x, y, z);
}
starsGeometry.addAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 5 });
const starField = new THREE.Points(starsGeometry, starsMaterial);
scene.add(starField);
// Particles setup
const particleGeometry = new THREE.BufferGeometry();
const particles = [];
for (let i = 0; i < 5000; i++) {
const radius = Math.random() * 2 + 1;
const angle1 = Math.random() * Math.PI;
const angle2 = Math.random() * 2 * Math.PI;
const x = radius * Math.sin(angle1) * Math.cos(angle2);
const y = radius * Math.sin(angle1) * Math.sin(angle2);
const z = radius * Math.cos(angle1);
particles.push(x, y, z);
}
particleGeometry.addAttribute('position', new THREE.Float32BufferAttribute(particles, 3));
const particleMaterial = new THREE.PointsMaterial({ color: 0xff00ff, size: 1 });
const particlesMesh = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particlesMesh);
// Animation loop
let time = Date.now();
function animate() {
requestAnimationFrame(animate);
const currentTime = Date.now();
const delta = (currentTime - time) / 1000;
time = currentTime;
particlesMesh.rotation.x += 0.005;
particlesMesh.rotation.y += 0.005;
// Mouse movement tilt effect
const mouseX = (event.clientX / window.innerWidth) * 2 - 1;
const mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
particlesMesh.rotation.x += 0.01 * mouseY;
particlesMesh.rotation.y += 0.01 * mouseX;
renderer.render(scene, camera);
}
animate();
// Handle window resize
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// FPS counter
let fpsTime = Date.now();
let frameCount = 0;
function updateFPS() {
frameCount++;
const now = Date.now();
if (now - fpsTime >= 1000) {
const fps = Math.round((frameCount * 1000) / (now - fpsTime));
document.getElementById('fps').textContent = `FPS: ${fps}`;
frameCount = 0;
fpsTime = now;
}
}
function animate() {
requestAnimationFrame(animate);
updateFPS();
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
```
This code sets up a basic Three.js scene with a starfield background and 5000 particles in a spiral galaxy-like motion. The particles rotate around the Z-axis, and they tilt based on mouse movement across the screen. An FPS counter is included at the top left corner of the canvas for real-time performance monitoring.
gemma4:e4b
This is a complex, high-performance animation that requires careful use of WebGL via Three.js.
Here is the complete, single-file HTML solution.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Galactic Particle Field</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000000;
cursor: none; /* Hide default cursor for immersive feel */
}
canvas {
display: block;
}
#fps-counter {
position: fixed;
top: 20px;
left: 20px;
color: #ffffff;
font-family: 'Courier New', monospace;
font-size: 18px;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 8px;
user-select: none;
pointer-events: none; /* Ensure it doesn't block interaction */
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
let mouseX = 0, mouseY = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
// --- Performance Tracking ---
let frameCount = 0;
let lastTime = performance.now();
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000000, 0.0005); // Adds depth effect
// 2. Camera Setup
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 3. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// 5. Create Particle Systems
createGalaxy();
createStarfield();
// Start the animation loop
animate();
}
/**
* Generates the main galaxy spiral particle system.
*/
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Generate particles in a spiral pattern
for (let i = 0; i < particleCount; i++) {
// Calculate angle (theta)
const theta = Math.random() * Math.PI * 2;
// Calculate distance from center (r) - making it vary with depth for the spiral effect
const r = Math.random() * 50 + 1;
// Calculate depth (z)
const z = Math.random() * 100 - 50;
// Spiral modification: Make radius slightly larger for particles further back
const effectiveRadius = r * (1 + Math.abs(z) / 100);
// Position: (X, Y, Z)
const x = Math.cos(theta) * effectiveRadius;
const y = (Math.random() - 0.5) * 5; // Slight vertical spread
const zPos = z;
positions.push(x, y, zPos);
// Assign random colors (vibrant nebula colors)
color.setHSL(Math.random(), Math.random(), Math.random() * 0.5 + 0.5);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors assigned to the geometry
transparent: true,
blending: THREE.AdditiveBlending // Makes particles glow when overlapping
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Generates a sparse, distant starfield background.
*/
function createStarfield() {
const starCount = 10000;
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < starCount; i++) {
// Spread stars far out in a large cube
const x = Math.random() * 200 - 100;
const y = Math.random() * 200 - 100;
const z = Math.random() * 200 - 100;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
color: 0xaaaaaa,
size: 0.2,
transparent: true,
blending: THREE.AdditiveBlending
});
starfieldParticles = new THREE.Points(geometry, material);
scene.add(starfieldParticles);
}
/**
* Handles window resizing to keep the canvas fullscreen.
*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Captures mouse movement for camera tilt response.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.5;
mouseY = (event.clientY - windowHalfY) * 0.5;
}
/**
* The main animation loop.
*/
function animate() {
requestAnimationFrame(animate);
const time = performance.now() * 0.001;
// 1. Particle Movement (Rotation)
const rotationSpeed = 0.0005;
galaxyParticles.rotation.y += rotationSpeed * 0.5;
galaxyParticles.rotation.x += rotationSpeed * 0.1;
starfieldParticles.rotation.y += rotationSpeed * 0.05;
starfieldParticles.rotation.x += rotationSpeed * 0.01;
// 2. Interactivity (Tilt Response)
// Smoothly transition the camera rotation based on mouse position
camera.position.x += (mouseX * 0.1 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 0.1 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// 3. Render the scene
renderer.render(scene, camera);
// 4. FPS Calculation
frameCount++;
const currentTime = performance.now();
const delta = currentTime - lastTime;
if (delta >= 1000) {
const fps = Math.round(frameCount * 1000 / delta);
document.getElementById('fps-counter').innerText = `FPS: ${fps}`;
// Reset for next calculation
lastTime = currentTime;
frameCount = 0;
}
}
// --- Initialization Call ---
init();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN, you can follow this example below. This code will include a starfield background, colorful particles rotating in a spiral galaxy-like pattern, and responsive to mouse movement (tilt). It will also display an FPS counter in the corner.
Here's how you can set up your HTML file:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fps { position: absolute; top: 10px; left: 10px; color: white; font-family: monospace; }
</style>
</head>
<body>
<div id="fps">FPS: 0</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Starfield background
const starsGeometry = new THREE.BufferGeometry();
const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
const starCount = 5000;
const positions = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
positions[i * 3] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 1] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 2] = Math.random() * 2000;
}
starsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const starField = new THREE.Points(starsGeometry, starsMaterial);
scene.add(starField);
// Camera setup
camera.position.z = 1000;
// Particles
const particlesGeometry = new THREE.BufferGeometry();
const particleCount = 5000;
const positionsArray = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const radius = Math.random() * 100 + 50;
const theta = Math.random() * Math.PI * 2;
const phi = Math.random() * Math.PI;
positionsArray[i * 3] = radius * Math.sin(phi) * Math.cos(theta);
positionsArray[i * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positionsArray[i * 3 + 2] = radius * Math.cos(phi);
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positionsArray, 3));
const particleMaterial = new THREE.PointsMaterial({ color: 0x87CEEB, size: 1 });
const particles = new THREE.Points(particlesGeometry, particleMaterial);
scene.add(particles);
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Rotate particles based on mouse movement
const mouseX = (event.clientX / window.innerWidth) * 2 - 1;
const mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
const rotationSpeed = 0.05;
particles.rotation.x += mouseY * rotationSpeed;
particles.rotation.y += mouseX * rotationSpeed;
renderer.render(scene, camera);
}
animate();
// Handle window resize
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// FPS counter
let fpsCounter = 0;
const startTime = Date.now();
function updateFPS() {
fpsCounter++;
if (Date.now() - startTime >= 1000) {
document.getElementById('fps').textContent = `FPS: ${fpsCounter}`;
fpsCounter = 0;
startTime = Date.now();
}
}
setInterval(updateFPS, 100);
</script>
</body>
</html>
```
This HTML file sets up a basic Three.js scene with a starfield and particles that rotate based on mouse movement. The FPS counter is updated every second to provide real-time performance feedback. You can copy this code into an HTML file and open it in your browser to see the animation.
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive 3D galaxy animation with 5000 particles, mouse interaction, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
cursor: none;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: rgba(255, 255, 255, 0.8);
font-size: 36px;
text-align: center;
z-index: 100;
text-shadow: 0 0 20px rgba(100, 150, 255, 0.8);
pointer-events: none;
opacity: 0.9;
}
#title span {
display: block;
font-size: 18px;
margin-top: 10px;
font-weight: normal;
}
#loading {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: #000;
z-index: 200;
transition: opacity 1s ease;
}
.spinner {
width: 50px;
height: 50px;
border: 5px solid rgba(255, 255, 255, 0.1);
border-top: 5px solid #4a90e2;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div id="container">
<div id="info">Interactive 3D Galaxy</div>
<div id="fps-counter">FPS: 0</div>
<div id="title">Galaxy Particle System<br><span>Move your mouse to interact</span></div>
<div id="loading">
<div class="spinner"></div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats = { fps: 0, frameCount: 0, lastTime: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 100, 300);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 150;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Hide loading screen
setTimeout(() => {
document.getElementById('loading').style.opacity = '0';
setTimeout(() => {
document.getElementById('loading').style.display = 'none';
}, 1000);
}, 1500);
// Start animation
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const material = new THREE.PointsMaterial({
size: 1.5,
sizeAttenuation: true,
vertexColors: true,
transparent: true,
opacity: 0.9
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy particles
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position particles in spiral galaxy pattern
const radius = Math.sqrt(Math.random()) * 100;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 20;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color particles with galaxy colors
const color = new THREE.Color();
const hue = (Math.random() * 0.3 + 0.5); // Blue to purple
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Size variation
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 100;
mouseY = (event.clientY - windowHalfY) / 100;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update FPS counter
updateFPS();
// Rotate particles
if (particles) {
particles.rotation.y += 0.001;
particles.rotation.x = mouseY * 0.05;
}
// Update camera position based on mouse
camera.position.x += (mouseX * 5 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 5 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
}
// Update FPS counter
function updateFPS() {
co
gemma4:e4b
This solution creates a self-contained HTML file that uses Three.js to render the particle system. It handles the geometry calculation for the spiral, implements mouse tracking for camera tilt, and includes a dedicated FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galactic Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: white;
font-family: monospace;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
z-index: 10;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js library from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starFieldParticles;
let clock = new THREE.Clock();
let mouseX = 0, mouseY = 0;
const container = document.body;
// --- Initialization Function ---
function init() {
// 1. Setup Scene, Camera, and Renderer
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
container.appendChild(renderer.domElement);
// Camera setup (Perspective camera is best for depth)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 2. Create the Galaxy Particle System
createGalaxyParticles(5000);
// 3. Create the Starfield Background
createStarField(10000);
// 4. Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Start the animation loop
animate();
}
// --- Geometry Generation Functions ---
/**
* Creates the spiraling galaxy structure.
* Uses mathematical equations to place points in a spiral pattern.
* @param {number} count The number of particles to generate.
*/
function createGalaxyParticles(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Parameters for the spiral:
const maxAngle = 10 * Math.PI; // How far the spiral extends (in radians)
const radiusScale = 3; // How quickly the radius grows
for (let i = 0; i < count; i++) {
// Calculate the angle (theta) for the particle
// We distribute the angles evenly up to maxAngle
const theta = (i / (count - 1)) * maxAngle;
// Spiral Calculation (R = a * theta, Z = b * theta)
const r = radiusScale * theta;
const x = r * Math.cos(theta);
const y = r * Math.sin(theta);
const z = Math.sin(theta * 0.5) * 10 + (i / count * 20); // Add a slight depth variation
positions.push(x, y, z);
// Color calculation: Use the angle to define the color gradient
const hue = theta / (2 * Math.PI) + (i / count);
color.setHSL(hue % 1, 0.8, 0.5);
// Store color components (R, G, B)
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup
const material = new THREE.PointsMaterial({
size: 0.3,
vertexColors: true, // Use the colors defined in the geometry
transparent: true,
opacity: 0.9
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a uniform, distant starfield background.
* @param {number} count The number of stars.
*/
function createStarField(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
// Starfield positions are random and spread over a large area
for (let i = 0; i < count; i++) {
// Random coordinates within a large cube (-100 to 100)
const x = (Math.random() - 0.5) * 200;
const y = (Math.random() - 0.5) * 200;
const z = (Math.random() - 0.5) * 200;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// Material setup (simple white dots)
const material = new THREE.PointsMaterial({
size: 0.5,
color: 0xffffff,
sizeAttenuation: true
});
starFieldParticles = new THREE.Points(geometry, material);
scene.add(starFieldParticles);
}
// --- Event Handlers ---
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
// Normalize mouse coordinates to a range of -1 to 1
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
// --- Animation Loop and Logic ---
function animate() {
requestAnimationFrame(animate);
// 1. Time and Performance Tracking
const delta = clock.getDelta();
const elapsed = clock.getElapsedTime();
// 2. Animation Updates (Rotation)
// Rotate the galaxy slowly
galaxyParticles.rotation.y += 0.0005 * delta * 60;
galaxyParticles.rotation.x = Math.sin(elapsed * 0.1) * 0.1;
// Subtle rotation for the background stars
starFieldParticles.rotation.y += 0.0001 * delta * 60;
// 3. Mouse Tilt Response (Camera LookAt)
// Smoothly interpolate camera position/rotation based on mouse movement
const targetRotationX = mouseY * 0.2;
const targetRotationY = mouseX * 0.2;
camera.rotation.y += (targetRotationY - camera.rotation.y) * 0.05;
camera.rotation.x += (targetRotationX - camera.rotation.x) * 0.05;
// 4. Render the scene
renderer.render(scene, camera);
// 5. Update FPS Counter
updateFPS(delta);
}
// --- FPS Counter Logic ---
let frameCount = 0;
let lastTime = performance.now();
const fpsElement = document.getElementById('fps-counter');
function updateFPS(delta) {
frameCount++;
const currentTime = performance.now();
const timeElapsed = currentTime - lastTime;
if (timeElapsed >= 1000) {
const fps = (frameCount * 1000) / timeElapsed;
fpsElement.textContent = `FPS: ${fps.toFixed(0)}`;
// Reset counters for the next second
frameCount = 0;
lastTime = currentTime;
}
}
// --- Execution ---
init();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN, you can follow this example. This code will include a starfield background, colorful particles rotating in a galaxy-like spiral, and respond to mouse movement by tilting the scene. Additionally, it will display an FPS (Frames Per Second) counter in the corner.
Here's how you can set up your HTML file:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fpsCounter { position: absolute; top: 10px; left: 10px; color: white; }
</style>
</head>
<body>
<div id="fpsCounter">FPS: -</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Setup Three.js scene, camera, and renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create a starfield background
const starsGeometry = new THREE.BufferGeometry();
const starsMaterial = new THREE.PointsMaterial({ color: 0xFFFFFF, size: 0.1 });
let starVertices = [];
for (let i = 0; i < 5000; i++) {
let vertex = new THREE.Vector3(Math.random() * 2000 - 1000, Math.random() * 2000 - 1000, Math.random() * 2000 - 1000);
starVertices.push(vertex.x, vertex.y, vertex.z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const starField = new THREE.Points(starsGeometry, starsMaterial);
scene.add(starField);
// Create particles
const particleCount = 5000;
const positions = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
positions[i * 3] = Math.random() * 1000 - 500;
positions[i * 3 + 1] = Math.random() * 1000 - 500;
positions[i * 3 + 2] = Math.random() * 1000 - 500;
}
const particlesGeometry = new THREE.BufferGeometry();
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const particlesMaterial = new THREE.PointsMaterial({ color: Math.random() * 0xFFFFFF, size: 2 });
const particles = new THREE.Points(particlesGeometry, particlesMaterial);
scene.add(particles);
// Animate the particles and camera
let mouseX = 0, mouseY = 0;
window.addEventListener('mousemove', (event) => {
mouseX = event.clientX / window.innerWidth * 2 - 1;
mouseY = -(event.clientY / window.innerHeight * 2) + 1;
});
function animate() {
requestAnimationFrame(animate);
particles.rotation.x += 0.005;
particles.rotation.y += 0.005;
camera.position.z = mouseY * -300;
camera.position.x = mouseX * 300;
camera.lookAt(scene.position);
renderer.render(scene, camera);
}
animate();
// FPS Counter
let fpsCounter = document.getElementById('fpsCounter');
function displayFPS() {
requestAnimationFrame(displayFPS);
const time = performance.now() * 0.001;
if (time % 1 === 0) {
fpsCounter.textContent = `FPS: ${Math.round(1 / (time - prevTime))}`;
}
prevTime = time;
}
let prevTime = 0;
displayFPS();
</script>
</body>
</html>
```
This code sets up a basic Three.js scene with a starfield and particles that rotate based on mouse movement. The FPS counter is updated every second to provide real-time performance data. Adjust the parameters such as particle count, size, and speed according to your preference for visual effects or performance considerations.
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D galaxy animation with 5000 particles, mouse interaction, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: #fff;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff7eb3, #ff70a6);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
margin: 5px 0;
font-size: 0.9rem;
opacity: 0.8;
}
#fps-counter {
position: absolute;
bottom: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-family: monospace;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#instructions {
position: absolute;
bottom: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-size: 0.9rem;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
canvas {
display: block;
}
.highlight {
color: #ff7eb3;
font-weight: bold;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>3D Galaxy Particle Animation</h1>
<p>Interactive <span class="highlight">5000</span> particle galaxy with spiral rotation</p>
<p>Move mouse to tilt the galaxy</p>
<p>Experience the beauty of space</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move mouse to tilt | Click to pause/resume</div>
</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats = { fps: 0, lastFpsUpdate: 0 };
let isPaused = false;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 15, 30);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 25;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
document.addEventListener('click', togglePause);
window.addEventListener('resize', onWindowResize);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Start animation
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.1,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const material = new THREE.PointsMaterial({
size: 0.15,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true
});
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy particles with spiral pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral galaxy pattern
const radius = Math.sqrt(Math.random()) * 15;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 3;
const x = Math.cos(angle) * radius;
const y = Math.sin(angle) * radius;
const z = height;
positions[i3] = x;
positions[i3 + 1] = y;
positions[i3 + 2] = z;
// Color variation
const color = new THREE.Color();
const hue = (i / particleCount) * 0.5 + 0.5; // Blue to purple
const saturation = 0.8 + Math.random() * 0.2;
const lightness = 0.4 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Size variation
sizes[i] = 0.1 + Math.random() * 0.3;
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.Float32BufferAttribute(sizes, 1));
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.0005;
mouseY = (event.clientY - windowHalfY) * 0.0005;
}
// Toggle pause/resume
function togglePause() {
isPaused = !isPaused;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
if (!isPaused) {
const delta = clock.getDelta();
const time = clock.getElapsedTime();
// Rotate particles
particles.rotation.x = time * 0.01;
particles.rotation.y = time * 0.02;
// Mouse tilt effect
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// Update FPS counter
updateFPS();
}
// Update controls
controls.update();
renderer.render(scene, camera);
}
// U
gemma4:e4b
This is a complex, performance-intensive animation. The solution below uses modern JavaScript features and best practices for Three.js to ensure smooth, frame-rate-aware rendering.
Since this is a single HTML file, all CSS, JavaScript, and the Three.js library loading are contained within it.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive Galaxy Particle Field</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000000;
}
canvas {
display: block;
}
#fps-counter {
position: fixed;
top: 10px;
left: 10px;
color: #ffffff;
font-family: 'Arial', sans-serif;
font-size: 16px;
padding: 5px 10px;
background: rgba(0, 0, 0, 0.5);
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Load Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starParticles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
// FPS tracking variables
let frameCount = 0;
let lastTime = performance.now();
const fpsCounterElement = document.getElementById('fps-counter');
// --- Initialization ---
function init() {
// 1. Setup Renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// 2. Setup Scene
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x000000, 1, 1000);
// 3. Setup Camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 100;
// 4. Create Particle Systems
createStarfield();
createGalaxySpiral(5000);
// 5. Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Start the animation loop
animate();
}
/**
* Generates a sparse, far-away starfield background.
*/
function createStarfield() {
const starCount = 10000;
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
for (let i = 0; i < starCount; i++) {
// Random positions far away
const x = THREE.MathUtils.randFloatSpread(2000);
const y = THREE.MathUtils.randFloatSpread(2000);
const z = THREE.MathUtils.randFloat(-2000, 2000);
positions.push(x, y, z);
// Random colors (soft white/blue)
const color = new THREE.Color();
color.setHSL(Math.random(), 0.7, 0.5);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8
});
starParticles = new THREE.Points(geometry, material);
scene.add(starParticles);
}
/**
* Generates particles arranged in a spiral pattern (Galaxy effect).
* Uses parametric equations for the spiral.
* @param {number} count The number of particles to generate.
*/
function createGalaxySpiral(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < count; i++) {
// Parameter t determines position along the spiral path
const t = (i / count) * Math.PI * 10;
// Spiral equations (r = a + b*t, theta = t / c)
// Radial distance (r) increases with 't'
const r = 50 + (i / count) * 150;
// Z position controls depth/perspective
const z = Math.sin(t) * 50 + 50;
// X and Y positions based on polar coordinates (r, angle)
const x = r * Math.cos(t * 0.5);
const y = r * Math.sin(t * 0.5);
positions.push(x, y, z);
// Color mapping based on position (creating a gradient effect)
const hue = (i / count) * 0.8 + 0.1;
color.setHSL(hue, 0.8, 0.6);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Handles window resizing to keep the canvas full screen.
*/
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Tracks mouse movement for interactive rotation.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.5;
mouseY = (event.clientY - windowHalfY) * 0.5;
}
/**
* The main animation loop.
* @param {number} time The current time timestamp.
*/
function animate(time) {
requestAnimationFrame(animate);
// --- 1. Update Animations ---
// Rotate the galaxy particles slowly for continuous motion
galaxyParticles.rotation.y += 0.0002;
galaxyParticles.rotation.x += 0.0001;
// Simulate rotation and movement for the starfield (subtle breathing effect)
starParticles.rotation.y += 0.00005;
starParticles.rotation.z += 0.00005;
// --- 2. Interaction (Mouse Tilt) ---
// Smoothly adjust camera rotation based on mouse position
camera.rotation.y += (mouseX * 0.0001 - camera.rotation.y) * 0.05;
camera.rotation.x += (-mouseY * 0.0001 - camera.rotation.x) * 0.05;
// --- 3. Render ---
renderer.render(scene, camera);
// --- 4. FPS Counter Update ---
frameCount++;
const elapsed = performance.now() - lastTime;
if (elapsed >= 1000) {
const fps = Math.round(frameCount * 1000 / elapsed);
fpsCounterElement.textContent = `FPS: ${fps}`;
frameCount = 0;
lastTime = performance.now();
}
}
// --- Execution Start ---
init();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN, you can follow the steps below. This example will include a starfield background, colorful particles rotating in a galaxy-like spiral, and a FPS counter in the corner that responds to mouse movement for tilting effects.
Here's how you can create this interactive 3D particle animation:
1. **Create an HTML file** where you will embed your Three.js script along with CSS and JavaScript.
2. **Set up the basic structure**: Include necessary scripts from CDN, define a canvas for rendering in HTML, and include some basic styles for layout.
Here's how your HTML file (`index.html`) should look:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fps { position: absolute; top: 10px; left: 10px; color: white; }
</style>
</head>
<body>
<div id="fps">FPS: -</div>
<script src="https://cdn.jsdelivr.net/npm/three.js@0.140.0/build/three.min.js"></script>
<script>
// Your JavaScript code will go here
</script>
</body>
</html>
```
3. **Write the JavaScript to create and animate particles**: Use Three.js for creating a scene, camera, renderer, and particle system. Add mouse movement controls to tilt the galaxy.
Here's how you can add the JavaScript code:
```javascript
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Particle system setup
const particles = new THREE.Geometry();
for (let i = 0; i < 5000; i++) {
const particle = new THREE.Vector3();
particle.x = Math.random() * 100 - 50;
particle.y = Math.random() * 100 - 50;
particle.z = Math.random() * 100 - 50;
particles.vertices.push(particle);
}
const particleMaterial = new THREE.PointsMaterial({ color: 0xFFFFFF, size: 2 });
const particleSystem = new THREE.Points(particles, particleMaterial);
scene.add(particleSystem);
// Camera position
camera.position.z = 500;
// Mouse movement controls for rotation
const mouse = new THREE.Vector2();
window.addEventListener('mousemove', (event) => {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
});
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Rotate the particles to create a spiral effect
particleSystem.rotation.x += 0.005;
particleSystem.rotation.y += 0.005;
// Tilt based on mouse movement
const rotationFactor = 0.1;
particleSystem.rotation.z = mouse.x * rotationFactor;
particleSystem.rotation.y = mouse.y * -rotationFactor;
renderer.render(scene, camera);
}
animate();
// FPS counter
let fpsCounter = document.getElementById('fps');
function updateFPS() {
let now = Date.now();
if (now - startTime >= 100) {
fpsCounter.textContent = 'FPS: ' + frameCount;
frameCount = 0;
startTime = now;
}
requestAnimationFrame(updateFPS);
}
let startTime = Date.now();
let frameCount = 0;
function update() {
frameCount++;
requestAnimationFrame(update);
}
requestAnimationFrame(update);
```
4. **Run the HTML file** in a web browser to see your interactive 3D particle animation with mouse-controlled tilting and a starfield background.
This setup uses Three.js for rendering, handling 3D graphics, and animations. CSS is used for basic styling, and JavaScript handles all the interactive components including mouse movement tracking, particle dynamics, and FPS calculation.
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy-like particle animation with mouse interaction and a starfield background using Three.js. Here's the complete solution:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
cursor: pointer;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: rgba(255, 255, 255, 0.8);
font-size: 28px;
text-align: center;
z-index: 100;
text-shadow: 0 0 15px rgba(100, 150, 255, 0.7);
opacity: 0.8;
transition: opacity 1s;
}
#title:hover {
opacity: 1;
}
.instructions {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
color: rgba(255, 255, 255, 0.6);
font-size: 16px;
text-align: center;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 20px;
border-radius: 20px;
backdrop-filter: blur(5px);
}
</style>
</head>
<body>
<div id="container">
<div id="info">Galaxy Particle Simulation</div>
<div id="fps-counter">FPS: 0</div>
<div id="title">Interactive 3D Galaxy</div>
<div class="instructions">Move your mouse to tilt the galaxy | Click to change color scheme</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats = { fps: 0, lastFpsUpdate: 0 };
let colorScheme = 0;
const colorSchemes = [
[0.5, 0.2, 1.0], // Purple
[0.0, 0.7, 1.0], // Blue
[1.0, 0.3, 0.2], // Red
[0.2, 1.0, 0.5], // Green
[1.0, 0.8, 0.2] // Yellow
];
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Create starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
document.addEventListener('click', changeColorScheme);
window.addEventListener('resize', onWindowResize);
// Start animation
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const particleGeometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
const color = new THREE.Color();
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position particles in a spiral galaxy pattern
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 40;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Set colors
const colorScheme = colorSchemes[Math.floor(Math.random() * colorSchemes.length)];
color.setRGB(
Math.random() * colorScheme[0],
Math.random() * colorScheme[1],
Math.random() * colorScheme[2]
);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Set sizes
sizes[i] = Math.random() * 2 + 0.5;
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
particleGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
const particleMaterial = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Change color scheme
function changeColorScheme() {
colorScheme = (colorScheme + 1) % colorSchemes.length;
// Update particle colors
const colors = particles.geometry.attributes.color.array;
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
const colorScheme = colorSchemes[colorScheme];
const color = new THREE.Color();
color.setRGB(
Math.random() * colorScheme[0],
Math.random() * colorScheme[1],
Math.random() * colorScheme[2]
);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
particles.geometry.attributes.color.needsUpdate = true;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update FPS counter
const delta = clock.getDelta();
stats.fps = Math.round(1 / delta);
// Update FPS display
const fpsElement = document.getElementById('f
gemma4:e4b
This is a complex, highly interactive visualization that requires careful management of resources (5000 particles, continuous animation, and event handling).
Below is the complete single-file HTML solution.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Spiral Galaxy Particles</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000000;
font-family: 'Arial', sans-serif;
}
canvas {
display: block;
}
#fps-counter {
position: absolute;
top: 10px;
right: 10px;
color: #ffffff;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
font-size: 14px;
z-index: 10;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starParticles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
// --- FPS Tracking Variables ---
let frameCount = 0;
let lastTime = performance.now();
const fpsElement = document.getElementById('fps-counter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// 1. Setup Scene
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000000, 0.0005);
// 2. Setup Camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 100;
// 3. Setup Renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. Create Particles
createGalaxy();
createStarfield();
// 5. Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Start the animation loop
animate();
}
/**
* Creates the main spiral galaxy particle system.
* @param {number} count - Number of particles.
*/
function createGalaxy() {
const particleCount = 5000;
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const color = new THREE.Color();
// Galaxy parameters
const maxRadius = 80;
const spiralArms = 3;
// Populate positions and colors
for (let i = 0; i < particleCount; i++) {
const t = Math.random() * Math.PI * 2; // Angle around the center
const r = Math.pow(Math.random(), 1.5) * maxRadius; // Radial distance (weighted towards center)
const z_depth = r * 0.5;
// Apply a spiral pattern (increasing radius with decreasing angle)
// We use sin/cos to create the spiral shape
const angle = t * 0.5 + (i / particleCount) * Math.PI * 3;
const x = r * Math.cos(angle);
const y = r * Math.sin(angle) * 0.5; // Flatten the y-axis slightly
const z = r * Math.sin(angle) * 0.5;
// Store positions
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
// Store random colors (for the "colorful" requirement)
color.setHSL(Math.random(), 0.8, 0.5);
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
}
// Geometry and Material Setup
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors defined in the attributes
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a dense, distant starfield background.
*/
function createStarfield() {
const starCount = 10000;
const positions = new Float32Array(starCount * 3);
const color = new THREE.Color();
for (let i = 0; i < starCount; i++) {
// Distribute stars randomly in a large cube
positions[i * 3] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 1] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 2] = (Math.random() - 0.5) * 2000;
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
color: 0xaaaaaa,
size: 1,
transparent: true,
opacity: 0.7
});
starParticles = new THREE.Points(geometry, material);
scene.add(starParticles);
}
/**
* Handles mouse movement for camera tilt effect.
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.5;
mouseY = (event.clientY - windowHalfY) * 0.5;
}
/**
* Handles window resizing.
*/
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Main animation loop.
* @param {number} timestamp - High-resolution timestamp.
*/
function animate(timestamp) {
requestAnimationFrame(animate);
// --- 1. Calculate Delta Time and FPS ---
const time = performance.now();
const delta = time - lastTime;
lastTime = time;
frameCount++;
const elapsed = time - (lastTime - (1000 / 60) * (frameCount - 1));
if (elapsed >= 1000) {
const fps = Math.round(frameCount / (elapsed / 1000));
fpsElement.textContent = `FPS: ${fps}`;
frameCount = 0;
lastTime = time;
}
// --- 2. Camera Movement (Mouse Interaction) ---
// Smoothly interpolate camera target based on mouse position
camera.position.x += (mouseX * 0.001 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 0.001 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// --- 3. Galaxy Animation ---
// Continuous rotation and subtle pulse
galaxyParticles.rotation.y += 0.0005;
galaxyParticles.rotation.x += 0.0002;
// Make the galaxy appear to pulse slowly
galaxyParticles.scale.set(1 + Math.sin(timestamp / 1500) * 0.05,
1 + Math.sin(timestamp / 1500) * 0.05,
1 + Math.sin(timestamp / 1500) * 0.05);
// --- 4. Starfield Animation ---
// Make the stars slowly drift and rotate, simulating vast space movement
starParticles.rotation.y += 0.00005;
starParticles.rotation.x += 0.00002;
// --- 5. Rendering ---
renderer.render(scene, camera);
}
// Start the application
init();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN, you can follow the steps below to build a simple yet visually appealing galaxy-like spiral particle system that responds to mouse movement and displays a starfield background along with an FPS counter.
Here's how you can set up your HTML file:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Galaxy Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fps { position: absolute; top: 10px; left: 10px; color: white; }
</style>
</head>
<body>
<div id="fps">FPS: N/A</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Starfield background
const starCount = 5000;
const starsGeometry = new THREE.BufferGeometry();
const positions = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
positions[i * 3] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 1] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 2] = (Math.random() - 0.5) * 2000;
}
starsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const starMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
const stars = new THREE.Points(starsGeometry, starMaterial);
scene.add(stars);
// Camera setup
camera.position.z = 500;
// Particle system
const particleCount = 5000;
const particlesGeometry = new THREE.BufferGeometry();
const positionsParticles = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const x = (Math.random() - 0.5) * 1000;
const y = (Math.random() - 0.5) * 1000;
const z = (Math.random() - 0.5) * 1000;
positionsParticles[i * 3] = x;
positionsParticles[i * 3 + 1] = y;
positionsParticles[i * 3 + 2] = z;
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positionsParticles, 3));
const particleMaterial = new THREE.PointsMaterial({ color: Math.random() * 0xffffff, size: 1 });
const particles = new THREE.Points(particlesGeometry, particleMaterial);
scene.add(particles);
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Rotate the galaxy-like spiral effect based on mouse movement
const mouseX = (event.clientX / window.innerWidth) * 2 - 1;
const mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
particles.rotation.x += mouseY * 0.001;
particles.rotation.y += mouseX * 0.001;
// Render the scene
renderer.render(scene, camera);
}
animate();
// Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// FPS counter
let fps = 0;
const startTime = Date.now();
function updateFPS() {
fps++;
if (Date.now() - startTime >= 1000) {
document.getElementById('fps').innerText = `FPS: ${fps}`;
fps = 0;
startTime = Date.now();
}
}
setInterval(updateFPS, 10);
</script>
</body>
</html>
```
This code sets up a basic Three.js scene with a starfield background and a galaxy-like spiral particle system that rotates based on mouse movement. The FPS counter is updated every second to provide real-time performance feedback. Adjust the parameters for particles, such as count, size, and color, to further customize the visual appearance of your animation.
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D particle galaxy animation with mouse tilt response and a starfield background. Here's the complete solution in a single HTML file:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: #fff;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
max-width: 300px;
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(to right, #ff8a00, #e52e71);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(229, 46, 113, 0.3);
}
#info p {
font-size: 1rem;
margin-bottom: 15px;
line-height: 1.5;
}
#info ul {
padding-left: 20px;
margin-bottom: 15px;
}
#info li {
margin-bottom: 8px;
font-size: 0.9rem;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
font-family: monospace;
font-size: 1.2rem;
}
#loading {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: #000;
z-index: 1000;
transition: opacity 1s ease-out;
}
#loading-text {
font-size: 2rem;
text-align: center;
background: linear-gradient(to right, #ff8a00, #e52e71);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 20px rgba(229, 46, 113, 0.5);
}
.pulse {
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 0.7; }
50% { opacity: 1; }
100% { opacity: 0.7; }
}
#credits {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
backdrop-filter: blur(5px);
font-size: 0.9rem;
text-align: center;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>Experience a galaxy of 5000 colorful particles rotating in a spiral formation.</p>
<ul>
<li>Move your mouse to tilt the galaxy</li>
<li>Particles respond to mouse movement</li>
<li>Starfield background for immersive effect</li>
<li>Real-time FPS counter</li>
</ul>
<p>Created with Three.js</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="loading">
<div id="loading-text" class="pulse">Loading Galaxy...</div>
</div>
<div id="credits">Three.js Particle Galaxy Animation</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let stats, clock;
let particleCount = 5000;
let galaxyRadius = 500;
let galaxyRotationSpeed = 0.001;
let starField;
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 1000, 3000);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 1000;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.enableZoom = true;
controls.enablePan = false;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add lighting
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1, 1000);
pointLight.position.set(0, 0, 0);
scene.add(pointLight);
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Initialize clock for FPS
clock = new THREE.Clock();
// Hide loading screen
setTimeout(() => {
document.getElementById('loading').style.opacity = '0';
setTimeout(() => {
document.getElementById('loading').style.display = 'none';
}, 1000);
}, 1500);
// Start animation
animate();
}
// Create the galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
const color = new THREE.Color();
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Position particles in a spiral galaxy pattern
const radius = Math.sqrt(Math.random()) * galaxyRadius;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 100;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Random particle size
sizes[i] = Math.random() * 3 + 1;
// Color based on position in galaxy
const spiralAngle = Math.atan2(positions[i3 + 2], positions[i3]);
const hue = (spiralAngle / (Math.PI * 2) + 0.5) * 0.8;
color.setHSL(hue, 1, 0.5);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create particle material
const material = new THREE.PointsMaterial({
size: 3,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 2,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
gemma4:e4b
This is a complex, high-performance visualization that requires careful management of geometry, rendering, and event handling.
Here is the complete single-file HTML implementation.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Galaxy Particle Field</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 10px;
left: 10px;
color: #ffffff;
font-family: monospace;
background: rgba(0, 0, 0, 0.5);
padding: 5px 10px;
border-radius: 5px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starfieldParticles;
let mouseX = 0;
let mouseY = 0;
let container = document.body;
// --- FPS Tracking Variables ---
let frameCount = 0;
let lastTime = performance.now();
const fpsCounterElement = document.getElementById('fps-counter');
// --- Initialization Function ---
function init() {
// 1. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 2. Scene Setup
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000000, 0.0005); // Subtle depth effect
// 3. Camera Setup
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
// 4. Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove);
// 5. Create Components
createStarfield();
createGalaxy();
// Start the animation loop
animate();
}
// --- Component Creation Functions ---
/**
* Creates a dense, random starfield background.
*/
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starCount = 10000;
const positions = [];
for (let i = 0; i < starCount; i++) {
// Distribute stars in a large cube area
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
positions.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const starMaterial = new THREE.PointsMaterial({
color: 0xaaaaee,
size: 1.5,
transparent: true,
blending: THREE.AdditiveBlending // Makes stars glow
});
starfieldParticles = new THREE.Points(starGeometry, starMaterial);
scene.add(starfieldParticles);
}
/**
* Creates the main particle system in a spiral galaxy formation.
*/
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
// Setup the spiral structure
const radiusMax = 30;
const spiralTurns = 5;
const particleSpacing = 0.1;
for (let i = 0; i < particleCount; i++) {
// Calculate angle and distance for a spiral shape
// The radius decreases as the angle increases (decay)
const angle = i * (Math.PI * 2 * spiralTurns / particleCount) + (Math.random() * 0.5);
// Formula for a decaying spiral: r = a * (1 - theta / max_theta)
const r = radiusMax * (1 - (angle / (Math.PI * 2 * spiralTurns)));
// Randomize the initial depth (z) slightly
const z = (Math.random() - 0.5) * 5;
// Convert polar coordinates to Cartesian
const x = r * Math.cos(angle);
const y = (Math.random() - 0.5) * 10; // Slight vertical spread
const depth = z + Math.sin(angle * 1.5) * 5; // Add wave depth
positions.push(x, y, depth);
// Assign random vibrant colors
const color = new THREE.Color(Math.random(), Math.random(), Math.random());
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true, // Use the colors defined in the geometry
blending: THREE.AdditiveBlending,
transparent: true,
depthWrite: false
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
// --- Event Handlers ---
/**
* Handles window resizing to keep the aspect ratio correct.
*/
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
/**
* Captures mouse movement data for camera/scene rotation.
*/
function onDocumentMouseMove(event) {
// Normalize mouse coordinates to range [-1, 1]
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
}
// --- Animation Loop ---
/**
* The main animation function called every frame.
* @param {number} time - The current timestamp.
*/
function animate(time) {
requestAnimationFrame(animate);
const delta = (time - lastTime) / 1000; // Time elapsed since last frame (in seconds)
lastTime = time;
frameCount++;
// 1. Update Particles (Rotation/Movement)
const timeFactor = time * 0.0005;
// Galaxy rotation (slow, continuous spin)
galaxyParticles.rotation.y += 0.0005;
galaxyParticles.rotation.x = Math.sin(timeFactor * 0.5) * 0.05;
// Starfield rotation (subtle parallax movement)
starfieldParticles.rotation.y += 0.00005;
starfieldParticles.rotation.x += 0.00005;
// 2. Camera/Scene Interaction (Mouse Tilt)
// Use mouse coordinates to smoothly adjust camera rotation
camera.rotation.y += (mouseX * 0.0005 - camera.rotation.y) * 0.1;
camera.rotation.x += (mouseY * 0.0005 - camera.rotation.x) * 0.1;
// 3. Rendering
renderer.render(scene, camera);
// 4. Update FPS Counter
if (frameCount % 30 === 0) {
const fps = Math.round(1 / (deltaTime || 0));
fpsCounterElement.textContent = `FPS: ${fps}`;
}
}
// --- Execution ---
init();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN, you can follow the steps below. This example will include a starfield background, colorful particles rotating in a spiral galaxy-like motion, and a FPS counter that responds to mouse movement for tilting effects.
Here's how you can set up this project:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fps { position: absolute; top: 10px; left: 10px; color: white; font-family: monospace; }
</style>
</head>
<body>
<div id="fps">FPS: 0</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Starfield background
const starsGeometry = new THREE.BufferGeometry();
const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
const starCount = 5000;
const positions = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
positions[i * 3] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 1] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 2] = (Math.random() - 0.5) * 2000;
}
starsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const starField = new THREE.Points(starsGeometry, starsMaterial);
scene.add(starField);
// Particle system
const particlesGeometry = new THREE.BufferGeometry();
const particleCount = 5000;
const positionsParticles = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const radius = Math.random() * 100;
const theta = Math.random() * Math.PI * 2;
const phi = Math.random() * Math.PI;
positionsParticles[i * 3] = radius * Math.sin(phi) * Math.cos(theta);
positionsParticles[i * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
positionsParticles[i * 3 + 2] = radius * Math.cos(phi);
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positionsParticles, 3));
const particleMaterial = new THREE.PointsMaterial({ color: 0x8888ff, size: 1 });
const particles = new THREE.Points(particlesGeometry, particleMaterial);
scene.add(particles);
// Camera position
camera.position.z = 500;
// Mouse movement for tilt effect
let mouseX = 0, mouseY = 0;
window.addEventListener('mousemove', (event) => {
mouseX = event.clientX - window.innerWidth / 2;
mouseY = event.clientY - window.innerHeight / 2;
});
// Animation loop
function animate() {
requestAnimationFrame(animate);
particles.rotation.x += 0.01;
particles.rotation.y += 0.01;
const tiltX = (mouseY / window.innerHeight) * 0.2;
const tiltY = (mouseX / window.innerWidth) * 0.2;
camera.position.x += (tiltX - (camera.position.x - particles.position.x)) * 0.05;
camera.position.y += (tiltY - (camera.position.y - particles.position.y)) * 0.05;
renderer.render(scene, camera);
}
// FPS counter
let fps = 0;
let frameCount = 0;
const startTime = Date.now();
function updateFPS() {
frameCount++;
const currentTime = Date.now();
if (currentTime - startTime >= 1000) {
fps = frameCount;
frameCount = 0;
startTime = currentTime;
}
document.getElementById('fps').textContent = `FPS: ${fps}`;
}
animate();
setInterval(updateFPS, 100);
</script>
</body>
</html>
```
This code sets up a basic Three.js scene with a starfield background and particles rotating in space. The camera responds to mouse movement for tilting effects, and an FPS counter is displayed at the top left corner of the screen. Adjust the parameters such as particle count, size, color, and camera settings to customize the appearance further.
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy-like particle animation with mouse interaction and a starfield background using Three.js. Here's the complete solution in a single HTML file:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Particle Animation</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
cursor: none;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
color: rgba(255, 255, 255, 0.7);
font-size: 14px;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
}
#title {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: rgba(255, 255, 255, 0.8);
font-size: 32px;
text-align: center;
z-index: 100;
text-shadow: 0 0 10px rgba(100, 150, 255, 0.7);
opacity: 0.8;
transition: opacity 2s;
}
#title:hover {
opacity: 1;
}
#instructions {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
color: rgba(255, 255, 255, 0.6);
font-size: 16px;
text-align: center;
z-index: 100;
background: rgba(0, 0, 0, 0.5);
padding: 10px 20px;
border-radius: 20px;
backdrop-filter: blur(5px);
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="info">Interactive 3D Galaxy Animation</div>
<div id="fps-counter">FPS: 0</div>
<div id="title">3D GALAXY PARTICLE SYSTEM</div>
<div id="instructions">Move your mouse to interact with the galaxy</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let particleCount = 5000;
let clock = new THREE.Clock();
let stats = { fps: 0, lastTime: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add starfield background
createStarfield();
// Create galaxy particles
createGalaxy();
// Add orbit controls for manual rotation
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// Event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Create galaxy particles
function createGalaxy() {
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create galaxy particles with spiral pattern
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral galaxy pattern
const radius = Math.sqrt(Math.random()) * 200;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 50;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color variations
const color = new THREE.Color();
const hue = (Math.random() * 0.4 + 0.5); // Blue to purple range
const saturation = 0.8;
const lightness = 0.5 + Math.random() * 0.3;
color.setHSL(hue, saturation, lightness);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Particle sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particles
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.0005;
mouseY = (event.clientY - windowHalfY) * 0.0005;
}
// Window resize handler
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update FPS counter
const delta = clock.getDelta();
stats.fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${stats.fps}`;
// Rotate particles
if (particles) {
particles.rotation.x += 0.0005;
particles.rotation.y += 0.001;
// Mouse interaction
camera.position.x += (mouseX * 50 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 50 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update controls
if (controls) {
controls.update();
}
// Render scene
renderer.render(scene, camera);
}
// Initialize the application
init();
</script>
</body>
</html>
```
## Features of this Interactive Galaxy Animation:
1. **5000 Colorful Particles**: Created in a spiral galaxy pattern with varying colors and sizes
2. **Mouse Interaction**: The galaxy tilts and rotates based on mouse movement
3. **Starfield Background**: Thousands of stars create a deep space background
4. **FPS Counter**: Displays real-time frames per second in the top-right corne
gemma4:e4b
This is a complex, resource-intensive animation. To ensure it runs smoothly and efficiently, we will use Three.js's `BufferGeometry` for the particles, which is optimized for large point clouds.
Here is the complete, single-file solution:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Interactive 3D Galaxy Particle Animation</title>
<style>
body { margin: 0; overflow: hidden; background-color: #000000; }
canvas { display: block; }
#fps-counter {
position: absolute;
top: 20px;
left: 20px;
color: #ffffff;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 18px;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 8px;
user-select: none;
z-index: 10;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Three.js CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starParticles;
let clock = new THREE.Clock();
let mouseX = 0, mouseY = 0;
// --- Constants ---
const NUM_GALAXY_PARTICLES = 5000;
const NUM_STAR_PARTICLES = 20000;
const GALAXY_SPIRAL_FACTOR = 1.5; // Controls how tightly wound the spiral is
// --- Initialization Function ---
function init() {
// 1. Setup Scene, Camera, and Renderer
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 50;
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 2. Lighting (Subtle ambient light)
scene.add(new THREE.AmbientLight(0x333333));
// 3. Create the Galaxy Particle System
galaxyParticles = createGalaxyParticles(NUM_GALAXY_PARTICLES);
scene.add(galaxyParticles);
// 4. Create the Starfield Background
starParticles = createStarfieldParticles(NUM_STAR_PARTICLES);
scene.add(starParticles);
// 5. Event Listeners
document.addEventListener('mousemove', onDocumentMouseMove, false);
window.addEventListener('resize', onWindowResize, false);
// Start the animation loop
animate();
}
/**
* Generates particles arranged in a spiral pattern (the galaxy).
* @param {number} count The number of particles to generate.
* @returns {THREE.Points} The particle system object.
*/
function createGalaxyParticles(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < count; i++) {
// Calculate position using spiral formula: r = a * theta
// Angle (theta) increases linearly
const theta = (i / count) * Math.PI * 4;
// Radius (r) increases with angle, creating the spiral
const r = GALAXY_SPIRAL_FACTOR * theta;
// Add some noise to the radius for a more natural look
const noiseFactor = (Math.random() - 0.5) * 0.5;
const finalR = r + noiseFactor;
// X, Y, Z coordinates
const x = finalR * Math.cos(theta);
const y = finalR * Math.sin(theta) * 0.5 + (Math.random() - 0.5) * 5; // Slight vertical variance
const z = finalR * Math.sin(theta) * 0.8;
positions.push(x, y, z);
// Assign random colors for variety
color.setHSL(Math.random(), 0.8, 0.5);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 0.5,
vertexColors: true, // Use the colors set in the attribute
transparent: true,
blending: THREE.AdditiveBlending, // Makes colors glow when overlapping
sizeAttenuation: true
});
const points = new THREE.Points(geometry, material);
return points;
}
/**
* Generates a random, dense starfield background.
* @param {number} count The number of stars to generate.
* @returns {THREE.Points} The particle system object.
*/
function createStarfieldParticles(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
for (let i = 0; i < count; i++) {
// Scatter stars in a large cube volume
const x = (Math.random() - 0.5) * 1000;
const y = (Math.random() - 0.5) * 1000;
const z = (Math.random() - 0.5) * 1000;
positions.push(x, y, z);
// Assign faint white/blue colors
colors.push(Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
blending: THREE.AdditiveBlending
});
const points = new THREE.Points(geometry, material);
return points;
}
// --- Event Handlers ---
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
// Normalize mouse coordinates to a range of -1 to 1
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = - (event.clientY / window.innerHeight) * 2 + 1;
}
// --- Animation Loop ---
let frameCount = 0;
let lastTime = performance.now();
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
// 1. Update Galaxy Particles (Rotation and movement)
// Rotate the galaxy slowly around its center
galaxyParticles.rotation.y += 0.001 * delta * 60;
galaxyParticles.rotation.x += 0.0005 * delta * 60;
// 2. Update Starfield (Slow, subtle drift)
starParticles.rotation.y += 0.00005 * delta * 60;
starParticles.rotation.x += 0.00003 * delta * 60;
// 3. Camera/Scene Interaction (Mouse Tilt)
// Use mouse movement to subtly influence camera rotation
camera.rotation.y += (mouseX * 0.0001 - camera.rotation.y) * 0.1;
camera.rotation.x += (mouseY * 0.0001 - camera.rotation.x) * 0.1;
// 4. Render
renderer.render(scene, camera);
// 5. FPS Counter Update
frameCount++;
const currentTime = performance.now();
const elapsed = currentTime - lastTime;
if (elapsed >= 1000) {
const fps = Math.round(frameCount * (1000 / elapsed));
document.getElementById('fps-counter').innerText = `FPS: ${fps}`;
// Reset for next calculation
frameCount = 0;
lastTime = currentTime;
}
}
// Start the application
init();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from the CDN, you can follow the steps below. This example includes a starfield background, colorful particles rotating in a spiral galaxy-like motion, and responsive to mouse movement for tilting. Additionally, it displays an FPS (Frames Per Second) counter in the corner.
Here's how you can set up this project:
1. **Create an HTML file** where you will include all necessary scripts and define the structure of your 3D scene.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Setup Three.js scene, camera, and renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create a starfield background
const starsGeometry = new THREE.BufferGeometry();
const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
let starVertices = [];
for (let i = 0; i < 5000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = Math.random() * 4000 - 2000;
starVertices.push(x, y, z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starsGeometry, starsMaterial);
scene.add(stars);
// Create particles
const particleCount = 5000;
const particlesGeometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const x = (Math.random() - 0.5) * 1000;
const y = (Math.random() - 0.5) * 1000;
const z = Math.random() * 4000 - 2000;
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const particleMaterial = new THREE.PointsMaterial({ color: Math.random() * 0xffffff, size: 1 });
const particles = new THREE.Points(particlesGeometry, particleMaterial);
scene.add(particles);
// Position the camera and add lighting
camera.position.z = 1500;
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(-1, 2, 4).normalize();
scene.add(light);
// Handle window resize
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const elapsedTime = clock.getElapsedTime();
particles.rotation.x += 0.01;
particles.rotation.y += 0.01;
// Update mouse movement for tilt effect
const mouseX = (event.clientX / window.innerWidth) * 2 - 1;
const mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
particles.rotation.y += 0.005 * mouseX;
particles.rotation.x += 0.005 * mouseY;
renderer.render(scene, camera);
}
animate();
</script>
</body>
</html>
```
This code sets up a basic Three.js scene with a starfield background and particles that rotate based on mouse movement for tilting. The `animate` function continuously updates the rotation of the particles and handles window resizing. You can further enhance this by adding more interactivity, effects, or optimizations as needed.
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN, you can follow the steps below. This example includes a starfield background, colorful particles rotating in a spiral galaxy-like motion, and responds to mouse movement by tilting the camera. Additionally, it displays an FPS counter in the corner for performance monitoring.
Here's how you can set up this project:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fps { position: absolute; top: 10px; left: 10px; color: white; }
</style>
</head>
<body>
<div id="fps">FPS: N/A</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Create a starfield background
const starsGeometry = new THREE.BufferGeometry();
const count = 5000;
const positions = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
positions[i * 3] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 1] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 2] = Math.random() * 2000;
}
starsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const starMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
const stars = new THREE.Points(starsGeometry, starMaterial);
scene.add(stars);
// Create particles
const particleGeometry = new THREE.BufferGeometry();
const particles = new Float32Array(count * 3);
for (let i = 0; i < count; i++) {
particles[i * 3] = (Math.random() - 0.5) * 100;
particles[i * 3 + 1] = (Math.random() - 0.5) * 100;
particles[i * 3 + 2] = Math.random() * 100;
}
particleGeometry.setAttribute('position', new THREE.BufferAttribute(particles, 3));
const particleMaterial = new THREE.PointsMaterial({ color: 0x88ccdd, size: 2 });
const particlesMesh = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particlesMesh);
camera.position.z = 1000;
// Handle window resize
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Animation loop
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const elapsedTime = clock.getElapsedTime();
// Rotate particles and stars
particlesMesh.rotation.x += 0.005;
particlesMesh.rotation.y += 0.005;
stars.rotation.z += 0.001;
// Update camera based on mouse movement
const mouseX = (event.clientX / window.innerWidth) * 2 - 1;
const mouseY = -(event.clientY / window.innerHeight) * 2 + 1;
camera.rotation.x = mouseY * 0.1;
camera.rotation.y = mouseX * 0.1;
renderer.render(scene, camera);
}
animate();
// FPS counter
let fps = 0;
function displayFPS() {
const div = document.getElementById('fps');
div.textContent = `FPS: ${fps}`;
requestAnimationFrame(displayFPS);
}
displayFPS();
</script>
</body>
</html>
```
This code sets up a basic Three.js scene with a starfield and particles, animates them in a simple way, and updates the camera based on mouse movement for interaction. The FPS counter is updated every frame using requestAnimationFrame.
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from CDN, you can follow the steps below. This example will include colorful particles rotating in a galaxy-like spiral, respond to mouse movement (tilt), have a starfield background, and show an FPS counter in the corner.
Here's a complete HTML file that sets up this animation:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fps { position: absolute; top: 10px; left: 10px; color: white; }
</style>
</head>
<body>
<div id="fps">FPS: 0</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Starfield background
const starsGeometry = new THREE.BufferGeometry();
const starPositions = [];
for (let i = 0; i < 5000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = Math.random() * 4000 - 2000;
starPositions.push(x, y, z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 1 });
const starsMesh = new THREE.Points(starsGeometry, starsMaterial);
scene.add(starsMesh);
// Particle system
const particlesGeometry = new THREE.BufferGeometry();
const particlePositions = [];
const particleColors = [];
for (let i = 0; i < 5000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = Math.random() * 4000 - 2000;
particlePositions.push(x, y, z);
particleColors.push(Math.random(), Math.random(), Math.random());
}
particlesGeometry.setAttribute('position', new THREE.Float32BufferAttribute(particlePositions, 3));
const particlesMaterial = new THREE.PointsMaterial({ size: 0.5, vertexColors: true });
const particlesMesh = new THREE.Points(particlesGeometry, particlesMaterial);
scene.add(particlesMesh);
camera.position.z = 1000;
// Mouse movement response
let mouseX = 0, mouseY = 0;
window.addEventListener('mousemove', (event) => {
mouseX = event.clientX - window.innerWidth / 2;
mouseY = event.clientY - window.innerHeight / 2;
});
// Animation loop
function animate() {
requestAnimationFrame(animate);
const tiltAngleX = (mouseX / window.innerWidth) * 0.1;
const tiltAngleY = -(mouseY / window.innerHeight) * 0.1;
camera.rotation.x += tiltAngleX;
camera.rotation.y += tiltAngleY;
renderer.render(scene, camera);
}
// FPS counter
let fps = 0;
const startTime = Date.now();
function countFPS() {
fps++;
const elapsedTime = Date.now() - startTime;
if (elapsedTime >= 1000) {
document.getElementById('fps').textContent = `FPS: ${fps}`;
fps = 0;
startTime = Date.now();
}
requestAnimationFrame(countFPS);
}
countFPS();
animate();
</script>
</body>
</html>
```
This code sets up a basic Three.js scene with a starfield background and particles that rotate in response to mouse movement. The FPS counter is updated every second, providing real-time performance feedback. You can copy this code into an HTML file and open it in your browser to see the animation.
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an impressive interactive 3D galaxy animation with 5000 particles, mouse interaction, starfield background, and FPS counter - all in a single HTML file.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#info {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
#info h1 {
font-size: 1.8rem;
margin-bottom: 10px;
background: linear-gradient(90deg, #ff7eb3, #ff70a6, #ff5296);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(255, 110, 179, 0.3);
}
#info p {
margin: 5px 0;
font-size: 0.9rem;
opacity: 0.8;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
font-family: monospace;
font-size: 1.2rem;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 100;
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 20px;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
text-align: center;
font-size: 0.9rem;
opacity: 0.8;
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="info">
<h1>Interactive 3D Galaxy</h1>
<p>5,000 colorful particles in spiral formation</p>
<p>Move mouse to tilt the galaxy</p>
</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move mouse to interact | Scroll to zoom</div>
</div>
<script>
// Main variables
let scene, camera, renderer, controls;
let particles, particleSystem;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0, lastTime: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
scene.fog = new THREE.Fog(0x000011, 100, 200);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 150;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
const color = new THREE.Color();
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
// Spiral galaxy formation
const radius = Math.sqrt(Math.random()) * 50;
const angle = Math.random() * Math.PI * 2;
const height = (Math.random() - 0.5) * 10;
positions[i3] = Math.cos(angle) * radius;
positions[i3 + 1] = height;
positions[i3 + 2] = Math.sin(angle) * radius;
// Color variations
const hue = (angle / (Math.PI * 2)) + Math.random() * 0.2;
color.setHSL(hue, 0.8, 0.6);
colors[i3] = color.r;
colors[i3 + 1] = color.g;
colors[i3 + 2] = color.b;
// Random sizes
sizes[i] = Math.random() * 2 + 0.5;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true,
transparent: true,
opacity: 0.9,
sizeAttenuation: true,
blending: THREE.AdditiveBlending
});
// Create particle system
particleSystem = new THREE.Points(geometry, material);
scene.add(particleSystem);
}
// Create starfield background
function createStarfield() {
const starGeometry = new THREE.BufferGeometry();
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 0.2,
transparent: true,
opacity: 0.8
});
const starVertices = [];
for (let i = 0; i < 10000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
starVertices.push(x, y, z);
}
starGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starVertices, 3));
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Handle mouse movement
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.0005;
mouseY = (event.clientY - windowHalfY) * 0.0005;
}
// Handle window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
const delta = clock.getDelta();
const elapsedTime = clock.getElapsedTime();
// Update particle system rotation
if (particleSystem) {
particleSystem.rotation.y += 0.001;
particleSystem.rotation.x = mouseY * 0.5;
particleSystem.rotation.z = mouseX * 0.2;
}
// Update camera position based on mouse
camera.position.x += (mouseX * 50 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 50 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
// Update controls
controls.update();
// Update FPS counter
updateFPS();
// Render the scene
renderer.render(scene, camera);
}
// Update FPS counter
function updateFPS() {
const now = performance.now();
if (now >= stats.lastTime + 1000) {
document.getElementById('fps-counter').textContent = `FPS: ${stats.fps}`;
stats.lastTime = now;
stats.fps = 0;
} else {
stats.fps++;
}
}
gemma4:e4b
This is a complex task requiring precise coordination between 3D geometry generation, event handling, and rendering loops.
The solution below creates a self-contained HTML file that includes the necessary libraries (Three.js), CSS, and JavaScript logic.
### Interactive Galaxy Particle Animation
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Galaxy Particle Field</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000000;
font-family: 'Arial', sans-serif;
}
canvas {
display: block;
}
#fps-counter {
position: fixed;
top: 10px;
left: 10px;
color: #ffffff;
background: rgba(0, 0, 0, 0.5);
padding: 8px 12px;
border-radius: 5px;
z-index: 100;
font-size: 1.1em;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Include Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let particles, particleGeometry, particleMaterial;
const PARTICLE_COUNT = 5000;
let mouseX = 0;
let mouseY = 0;
// --- FPS Tracking Variables ---
let frameCount = 0;
let lastTime = performance.now();
const fpsCounterElement = document.getElementById('fps-counter');
// --- Initialization Function ---
function init() {
// 1. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 2. Scene Setup
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2(0x000000, 0.0005); // Adds depth effect
// 3. Camera Setup
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 150;
// 4. Particle Generation (The Galaxy Spiral)
generateSpiralParticles();
// 5. Event Listeners
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mousemove', onDocumentMouseMove, false);
// Start the animation loop
animate();
}
/**
* Generates the 3D coordinates for the spiral galaxy structure.
* Uses BufferGeometry for performance.
*/
function generateSpiralParticles() {
particleGeometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
// Parameters for the spiral shape
const totalAngle = Math.PI * 10; // How many full rotations
const depthScale = 0.8; // How far back the spiral extends
for (let i = 0; i < PARTICLE_COUNT; i++) {
// Calculate the angle (phi) for the particle
const t = (i / PARTICLE_COUNT) * totalAngle;
// Spiral Radius: R = a * t + b (gives the characteristic spiral shape)
// The radius increases as the angle increases
const radius = 10 + (t / totalAngle) * 150;
// X, Y, Z coordinates (Polar to Cartesian)
const x = Math.cos(t) * radius;
const y = Math.sin(t) * radius * 0.5; // Flattened vertically
const z = t * depthScale; // Depth based on angle
positions.push(x, y, z);
// Assign a color based on position/index for gradient effect
// Color shifts from blue/purple (start) to yellow/white (end)
const normalizedT = t / totalAngle;
color.setHSL(0.6 - normalizedT * 0.4, 1, 0.5 + normalizedT * 0.2);
colors.push(color.r, color.g, color.b);
}
// Set geometry attributes
particleGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
particleGeometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
// Material setup
particleMaterial = new THREE.PointsMaterial({
size: 1.5, // Particle size
vertexColors: true, // Use the colors defined in the geometry
transparent: true,
opacity: 0.8
});
// Create the particle system
particles = new THREE.Points(particleGeometry, particleMaterial);
scene.add(particles);
}
// --- Event Handlers ---
function onWindowResize() {
camera.viewport.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
// Normalize mouse coordinates to the range [-1, 1]
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
mouseY = - (event.clientY / window.innerHeight) * 2 + 1;
}
// --- Animation Loop ---
function animate() {
requestAnimationFrame(animate);
// 1. Update Particle Animation
const time = Date.now() * 0.0001;
// Constant rotation (Galaxy spin)
particles.rotation.y += 0.0005;
particles.rotation.x = Math.sin(time * 0.1) * 0.05;
// 2. Mouse Interaction (Tilt)
// The tilt effect rotates the camera/scene based on mouse position
camera.position.x = mouseX * 50;
camera.position.y = mouseY * 50;
camera.lookAt(scene.position); // Keep the focus on the center
// 3. Rendering
renderer.render(scene, camera);
// 4. FPS Counter Update
updateFPS();
}
// --- Utility Functions ---
/**
* Updates the FPS counter display using performance timing.
*/
function updateFPS() {
const currentTime = performance.now();
const elapsed = currentTime - lastTime;
frameCount++;
// Calculate FPS every 500ms for smoother display
if (elapsed >= 500) {
const fps = Math.round(1000 / (elapsed / frameCount));
fpsCounterElement.textContent = `FPS: ${fps}`;
// Reset counters
frameCount = 0;
lastTime = currentTime;
}
}
// --- Execution ---
init();
</script>
</body>
</html>
```
deepseek-coder-v2:16b
Creating an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js involves several steps. Below is a simple implementation that includes all your requirements:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Starfield background
const starsGeometry = new THREE.BufferGeometry();
const starsMaterial = new THREE.PointsMaterial({ color: 0xFFFFFF, size: 0.1 });
const starCount = 5000;
const positions = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
positions[i * 3] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 1] = (Math.random() - 0.5) * 2000;
positions[i * 3 + 2] = (Math.random() - 0.5) * 2000;
}
starsGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const starField = new THREE.Points(starsGeometry, starsMaterial);
scene.add(starField);
// Galaxy-like spiral particles
const particleCount = 5000;
const positionsParticles = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const angle = i / particleCount * Math.PI * 2;
const radius = 5 + Math.random() * 4;
positionsParticles[i * 3] = Math.cos(angle) * radius;
positionsParticles[i * 3 + 1] = Math.sin(angle) * radius;
positionsParticles[i * 3 + 2] = (Math.random() - 0.5) * 40;
const colorIndex = i % 3;
colors[i * 3] = 1; // Red, Green, Blue
colors[i * 3 + 1] = Math.random(); // Random green
colors[i * 3 + 2] = Math.random(); // Random blue
}
const particlesGeometry = new THREE.BufferGeometry();
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positionsParticles, 3));
particlesGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
const particlesMaterial = new THREE.PointsMaterial({ size: 0.1, vertexColors: true });
const particles = new THREE.Points(particlesGeometry, particlesMaterial);
scene.add(particles);
// Camera setup and animation
camera.position.z = 40;
let mouseX = 0, mouseY = 0;
window.addEventListener('mousemove', (event) => {
mouseX = (event.clientX / window.innerWidth - 0.5) * 2;
mouseY = (event.clientY / window.innerHeight - 0.5) * 2;
});
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const elapsedTime = clock.getElapsedTime();
particles.rotation.x += 0.001;
particles.rotation.y += 0.001;
camera.position.z += (mouseY * 0.05 - camera.position.z) * 0.05;
camera.position.x += (mouseX * 0.05 - camera.position.x) * 0.05;
renderer.render(scene, camera);
}
animate();
// FPS counter
const stats = new Stats();
document.body.appendChild(stats.dom);
function updateStats() {
requestAnimationFrame(updateStats);
stats.begin();
stats.end();
}
updateStats();
</script>
</body>
</html>
```
### Explanation:
1. **Scene Setup**: A Three.js scene is created with a perspective camera and WebGL renderer. The background stars are added using buffer geometry and points material.
2. **Galaxy-like Spiral Particles**: Particle positions and colors are calculated to create a spiral effect, responding to mouse movement for tilt effects.
3. **Camera and Animation**: The camera's position is dynamically adjusted based on mouse movements, creating an interactive experience. Particles rotate smoothly due to continuous rotations applied in the animation loop.
4. **FPS Counter**: A simple FPS (frames per second) counter is added using a library (`stats.js`), which updates every frame for real-time performance monitoring.
This code provides a basic structure, and you can further enhance it by adding more complex geometries or interactions as needed.
qwen3-coder:30b
# Interactive 3D Galaxy Particle Animation
I'll create an immersive galaxy animation with 5000 colorful particles, responsive to mouse movement, with a starfield background and FPS counter.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive 3D Galaxy Animation</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
background: #000;
font-family: 'Arial', sans-serif;
color: white;
}
#container {
position: relative;
width: 100vw;
height: 100vh;
}
#fps-counter {
position: absolute;
top: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 10px 15px;
border-radius: 10px;
font-size: 14px;
z-index: 100;
}
#title {
position: absolute;
top: 20px;
left: 20px;
background: rgba(0, 0, 0, 0.7);
padding: 15px 20px;
border-radius: 10px;
font-size: 24px;
z-index: 100;
text-align: center;
}
#instructions {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, 0.7);
padding: 10px 20px;
border-radius: 10px;
font-size: 14px;
text-align: center;
z-index: 100;
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="container">
<div id="title">3D Galaxy Particle System</div>
<div id="fps-counter">FPS: 0</div>
<div id="instructions">Move your mouse to tilt the galaxy | Click and drag to rotate</div>
</div>
<script>
// Main variables
let scene, camera, renderer, particles, controls;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
let clock = new THREE.Clock();
let stats = { fps: 0, lastTime: 0 };
// Initialize the scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x000011);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.z = 500;
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.getElementById('container').appendChild(renderer.domElement);
// Add orbit controls
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.rotateSpeed = 0.5;
// Create galaxy particles
createGalaxy();
// Create starfield background
createStarfield();
// Add event listeners
document.addEventListener('mousemove', onDocumentMouseMove);
window.addEventListener('resize', onWindowResize);
// Start animation loop
animate();
}
// Create galaxy particles
function createGalaxy() {
const particleCount = 5000;
const galaxyRadius = 300;
const armCount = 4;
const armWidth = 0.5;
// Create particle geometry
const geometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
// Create particles in spiral arms
for (let i = 0; i < particleCount; i++) {
const radius = Math.random() * galaxyRadius;
const angle = Math.random() * Math.PI * 2;
// Create spiral arms
const armAngle = angle + Math.sin(radius / 50) * 0.5;
const spiralRadius = radius * (0.8 + Math.sin(radius / 30) * 0.2);
const x = Math.cos(armAngle) * spiralRadius;
const y = Math.sin(armAngle) * spiralRadius;
const z = (Math.random() - 0.5) * 20;
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
// Color based on position
const color = new THREE.Color();
const hue = (radius / galaxyRadius) * 0.3 + 0.5;
color.setHSL(hue, 1, 0.5);
colors[i * 3] = color.r;
colors[i * 3 + 1] = color.g;
colors[i * 3 + 2] = color.b;
// Size based on distance from center
sizes[i] = 1 + Math.random() * 3;
}
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// Create material
const material = new THREE.PointsMaterial({
size: 2,
vertexColors: true,
transparent: true,
opacity: 0.8,
sizeAttenuation: true
});
// Create particle system
particles = new THREE.Points(geometry, material);
scene.add(particles);
}
// Create starfield background
function createStarfield() {
const starCount = 10000;
const starGeometry = new THREE.BufferGeometry();
const starPositions = new Float32Array(starCount * 3);
for (let i = 0; i < starCount; i++) {
const radius = 500 + Math.random() * 1000;
const theta = Math.random() * Math.PI * 2;
const phi = Math.acos(2 * Math.random() - 1);
const x = radius * Math.sin(phi) * Math.cos(theta);
const y = radius * Math.sin(phi) * Math.sin(theta);
const z = radius * Math.cos(phi);
starPositions[i * 3] = x;
starPositions[i * 3 + 1] = y;
starPositions[i * 3 + 2] = z;
}
starGeometry.setAttribute('position', new THREE.BufferAttribute(starPositions, 3));
const starMaterial = new THREE.PointsMaterial({
color: 0xffffff,
size: 1.5,
sizeAttenuation: true
});
const stars = new THREE.Points(starGeometry, starMaterial);
scene.add(stars);
}
// Mouse move handler
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.001;
mouseY = (event.clientY - windowHalfY) * 0.001;
}
// Window resize handler
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
// Animation loop
function animate() {
requestAnimationFrame(animate);
// Update FPS counter
const delta = clock.getDelta();
stats.fps = Math.round(1 / delta);
document.getElementById('fps-counter').textContent = `FPS: ${stats.fps}`;
// Rotate particles
if (particles) {
particles.rotation.x += 0.0005;
particles.rotation.y += 0.001;
}
// Tilt based on mouse position
if (camera) {
camera.position.x += (mouseX * 10 - camera.position.x) * 0.05;
camera.position.y += (-mouseY * 10 - camera.position.y) * 0.05;
camera.lookAt(scene.position);
}
// Update controls
controls.update();
// Render scene
renderer.render(scene, camera);
}
// Start everything
init();
</script>
</body>
</html>
```
## Features of this Galaxy Animation:
1. **5000 Colorful Particles**: Created in a spiral galaxy pattern with varying colors and sizes
2. **Interactive Controls**:
- Mouse movement tilts the galaxy
- Click and drag to rotate the view
3. **Starfield Background**: 10,000 stars in a distant background
4. **FPS Counter**: Displays real-time frame rate in the top-right corner
5. **Responsive Design**: Adapts to any screen size
6. **Smooth Animations**: Optimized with requestAnimationFrame and damping controls
7. **Visual Effects**:
- Particle sizes vary bas
deepseek-coder-v2:16b
To create an interactive 3D particle animation using HTML, CSS, and JavaScript with Three.js from the CDN, you can follow this example below. This code will include a starfield background, colorful particles rotating in a spiral galaxy-like pattern, and a FPS (frames per second) counter responding to mouse movement.
Here's how you can set it up:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Particle Animation</title>
<style>
body { margin: 0; }
canvas { display: block; }
#fps { position: absolute; top: 10px; left: 10px; color: white; }
</style>
</head>
<body>
<div id="fps">FPS: 0</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Starfield background
const starsGeometry = new THREE.BufferGeometry();
const starsMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 0.1 });
let starPositions = [];
for (let i = 0; i < 5000; i++) {
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = Math.random() * 4000 - 2000;
starPositions.push(x, y, z);
}
starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starPositions, 3));
const stars = new THREE.Points(starsGeometry, starsMaterial);
scene.add(stars);
// Particles
const particleCount = 5000;
const particlesGeometry = new THREE.BufferGeometry();
const positions = new Float32Array(particleCount * 3);
for (let i = 0; i < particleCount; i++) {
const x = (Math.random() - 0.5) * 4000;
const y = (Math.random() - 0.5) * 4000;
const z = Math.random() * 4000 - 2000;
positions[i * 3] = x;
positions[i * 3 + 1] = y;
positions[i * 3 + 2] = z;
}
particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
const particleMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 2 });
const particles = new THREE.Points(particlesGeometry, particleMaterial);
scene.add(particles);
// Camera position
camera.position.z = 1500;
// Animation loop
let mouseX = 0, mouseY = 0;
const handleMouseMove = (event) => {
mouseX = event.clientX - window.innerWidth / 2;
mouseY = event.clientY - window.innerHeight / 2;
};
document.addEventListener('mousemove', handleMouseMove);
const animate = () => {
requestAnimationFrame(animate);
// Update camera position based on mouse movement
const rotationSpeed = 0.01;
camera.position.x += (mouseX * rotationSpeed) / window.innerWidth;
camera.position.y += (-mouseY * rotationSpeed) / window.innerHeight;
// Rotate particles and stars
particles.rotation.x += 0.01;
particles.rotation.y += 0.01;
stars.rotation.z += 0.005;
renderer.render(scene, camera);
};
animate();
// FPS counter
let fps = 0;
const prevTime = performance.now();
const updateFPS = () => {
const time = performance.now();
const deltaTime = (time - prevTime) / 1000;
if (deltaTime > 1) { // Update FPS every second
fps = Math.round(1 / deltaTime);
document.getElementById('fps').textContent = `FPS: ${fps}`;
prevTime = time;
}
requestAnimationFrame(updateFPS);
};
updateFPS();
</script>
</body>
</html>
```
This code sets up a basic 3D scene with a starfield background and particles that rotate in spiral patterns. The camera responds to mouse movement, creating an interactive experience. An FPS counter is included at the top-left corner of the screen for monitoring performance.
gemma4:e4b
This is a complex, highly visual project. To achieve the desired smoothness and performance, we will utilize `THREE.BufferGeometry` for the particles and implement a custom FPS counter and mouse-tracking logic.
Here is the complete, single-file HTML solution.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Interactive Galaxy Particle Field</title>
<style>
body {
margin: 0;
overflow: hidden;
background-color: #000000;
}
canvas {
display: block;
}
#fps-counter {
position: fixed;
top: 20px;
left: 20px;
color: #ffffff;
font-family: 'Arial', sans-serif;
font-size: 18px;
background: rgba(0, 0, 0, 0.5);
padding: 10px 15px;
border-radius: 8px;
z-index: 100;
}
</style>
</head>
<body>
<div id="fps-counter">FPS: 0</div>
<!-- Import Three.js from CDN -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// --- Global Variables ---
let scene, camera, renderer;
let galaxyParticles, starParticles;
let mouseX = 0, mouseY = 0;
let windowHalfX = window.innerWidth / 2;
let windowHalfY = window.innerHeight / 2;
// --- FPS Counter Logic ---
let frameCount = 0;
let lastTime = performance.now();
const fpsElement = document.getElementById('fps-counter');
/**
* Initializes the Three.js scene, camera, and renderer.
*/
function init() {
// 1. Scene Setup
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x000000, 1, 1000);
// 2. Camera Setup
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 2000);
camera.position.z = 50;
// 3. Renderer Setup
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 4. Event Listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('mousemove', onDocumentMouseMove);
// 5. Create Particle Systems
createGalaxyParticles(5000);
createStarfield(10000);
// Start the animation loop
animate();
}
/**
* Handles window resizing to keep the aspect ratio correct.
*/
function onWindowResize() {
camera.viewport.set(0, 0, 1, 1);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
}
/**
* Tracks mouse movement to influence camera rotation (tilt effect).
*/
function onDocumentMouseMove(event) {
mouseX = (event.clientX - windowHalfX) * 0.5;
mouseY = (event.clientY - windowHalfY) * 0.5;
}
/**
* Creates the main galaxy spiral particle system.
* @param {number} count - Number of particles.
*/
function createGalaxyParticles(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
const colors = [];
const color = new THREE.Color();
for (let i = 0; i < count; i++) {
// Calculate spiral position (using polar coordinates)
const angle = (i / count) * Math.PI * 8; // More wraps = tighter spiral
const distance = Math.sqrt(Math.random()) * 100; // Radius increases with distance
// X, Y, Z coordinates for the spiral
const x = Math.cos(angle) * distance * (1 + Math.random() * 0.5);
const y = Math.sin(angle) * distance * (1 + Math.random() * 0.5);
const z = Math.random() * 200 - 100; // Depth variation
positions.push(x, y, z);
// Assign random vibrant colors
color.setHSL(Math.random(), 1.0, 0.5 + Math.random() * 0.3);
colors.push(color.r, color.g, color.b);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
const material = new THREE.PointsMaterial({
size: 1.5,
vertexColors: true, // Use the colors assigned in the geometry
blending: THREE.AdditiveBlending,
transparent: true,
opacity: 0.8
});
galaxyParticles = new THREE.Points(geometry, material);
scene.add(galaxyParticles);
}
/**
* Creates a simple, distant starfield background.
* @param {number} count - Number of stars.
*/
function createStarfield(count) {
const geometry = new THREE.BufferGeometry();
const positions = [];
for (let i = 0; i < count; i++) {
// Position stars randomly in a massive cube
const x = (Math.random() - 0.5) * 2000;
const y = (Math.random() - 0.5) * 2000;
const z = (Math.random() - 0.5) * 2000;
positions.push(x, y, z);
}
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
const material = new THREE.PointsMaterial({
size: 1.5,
color: 0xaaaaee,
transparent: true,
opacity: 0.7
});
starParticles = new THREE.Points(geometry, material);
scene.add(starParticles);
}
/**
* The main animation loop.
* @param {number} time - Current time provided by requestAnimationFrame.
*/
function animate(time) {
requestAnimationFrame(animate);
// --- 1. Update Particle Positions (Rotation/Movement) ---
const timeFactor = time * 0.0005;
const positions = galaxyParticles.geometry.attributes.position.array;
for (let i = 0; i < 3; i++) { // Iterate through X, Y, Z
for (let j = 0; j < 3; j++) { // Iterate through particle groups (3 components)
const index = j * 3 + i;
// Apply rotation/wave effect to the galaxy
let x = positions[index];
let y = positions[index + 1];
let z = positions[index + 2];
// Gentle sinusoidal movement to make it feel alive
const offset = Math.sin(timeFactor + (j * 0.1)) * 5;
// Rotate around the Z axis based on time
positions[index] = x * Math.cos(timeFactor * 0.2) - y * Math.sin(timeFactor * 0.2);
positions[index + 1] = x * Math.sin(timeFactor * 0.2) + y * Math.cos(timeFactor * 0.2);
positions[index + 2] = z + Math.sin(timeFactor * 0.5 + j * 0.5) * 50;
}
}
galaxyParticles.geometry.attributes.position.needsUpdate = true;
// --- 2. Update Starfield (Slow movement) ---
const starPositions = starParticles.geometry.attributes.position.array;
const speed = 0.0005;
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
const index = j * 3 + i;
// Simulate stars moving slowly towards the camera
starPositions[index] += speed;
}
}
starParticles.geometry.attributes.position.needsUpdate = true;
// --- 3. Camera/View Interaction (Tilt) ---
// Smoothly interpolate camera rotation based on mouse input
camera.rotation.y += (mouseX * 0.0001 - camera.rotation.y) * 0.05;
camera.rotation.x += (mouseY * 0.0001 - camera.rotation.x) * 0.05;
// --- 4. Rendering ---
renderer.render(scene, camera);
// --- 5. FPS Calculation ---
frameCount++;
const timeDelta = performance.now() - lastTime;
if (timeDelta >= 1000) {
const fps = Math.round(frameCount * 1000 / timeDelta);
fpsElement.textContent = `FPS: ${fps}`;
// Reset counters
frameCount = 0;
lastTime = performance.now();
}
}
// --- Initialization Call ---
init();
</script>
</body>
</html>
```