Created
March 19, 2025 13:08
-
-
Save shricodev/79eec9915bde0b3847e066b1fad22ceb to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html> | |
| <body> | |
| <canvas id="canvas" width="800" height="600"></canvas> | |
| <script> | |
| const canvas = document.getElementById("canvas"); | |
| const ctx = canvas.getContext("2d"); | |
| // Initialize canvas | |
| ctx.fillStyle = "black"; | |
| ctx.fillRect(0, 0, canvas.width, canvas.height); | |
| // Configuration | |
| const RADIUS = 1; | |
| const LETTERS = [ | |
| "a", | |
| "b", | |
| "c", | |
| "d", | |
| "e", | |
| "f", | |
| "g", | |
| "h", | |
| "i", | |
| "j", | |
| "k", | |
| "l", | |
| "m", | |
| "n", | |
| "o", | |
| "p", | |
| "q", | |
| "r", | |
| "s", | |
| "t", | |
| "u", | |
| "v", | |
| "w", | |
| "x", | |
| "y", | |
| "z", | |
| ]; | |
| const NUM_POINTS = 400; | |
| const SCALE = 150; | |
| const CENTER_X = canvas.width / 2; | |
| const CENTER_Y = canvas.height / 2; | |
| // Generate points on sphere | |
| const points = Array.from({ length: NUM_POINTS }, (_, i) => { | |
| const theta = Math.acos(2 * Math.random() - 1); // Uniform distribution | |
| const phi = Math.random() * Math.PI * 2; | |
| return { | |
| x: RADIUS * Math.sin(theta) * Math.cos(phi), | |
| y: RADIUS * Math.sin(theta) * Math.sin(phi), | |
| z: RADIUS * Math.cos(theta), | |
| letter: LETTERS[i % LETTERS.length], | |
| }; | |
| }); | |
| // Rotation state | |
| let angleX = 0; | |
| let angleY = 0; | |
| // Animation loop | |
| function animate() { | |
| // Clear canvas | |
| ctx.fillStyle = "black"; | |
| ctx.fillRect(0, 0, canvas.width, canvas.height); | |
| // Prepare drawing context | |
| ctx.textAlign = "center"; | |
| ctx.textBaseline = "middle"; | |
| ctx.font = "14px Arial"; | |
| // Calculate rotated points | |
| const rotatedPoints = points.map((p) => { | |
| // X-axis rotation | |
| let y = p.y * Math.cos(angleX) - p.z * Math.sin(angleX); | |
| let z = p.y * Math.sin(angleX) + p.z * Math.cos(angleX); | |
| let x = p.x; | |
| // Y-axis rotation | |
| const x2 = x * Math.cos(angleY) + z * Math.sin(angleY); | |
| const z2 = -x * Math.sin(angleY) + z * Math.cos(angleY); | |
| return { | |
| x: x2, | |
| y: y, | |
| z: z2, | |
| letter: p.letter, | |
| }; | |
| }); | |
| // Sort points by depth (farthest first) | |
| rotatedPoints.sort((a, b) => a.z - b.z); | |
| // Draw points | |
| rotatedPoints.forEach((p) => { | |
| // Calculate color (white to gray based on depth) | |
| const gray = 128 + (p.z + 1) * 63.5; | |
| ctx.fillStyle = `rgb(${gray},${gray},${gray})`; | |
| // Project to 2D | |
| const x = p.x * SCALE + CENTER_X; | |
| const y = p.y * SCALE + CENTER_Y; | |
| ctx.fillText(p.letter, x, y); | |
| }); | |
| // Update angles | |
| angleX += 0.02; | |
| angleY += 0.03; | |
| requestAnimationFrame(animate); | |
| } | |
| animate(); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment