Created
December 23, 2025 16:43
-
-
Save pluto-atom-4/bba22be7329ccc9b43d017f900e4fe45 to your computer and use it in GitHub Desktop.
css visualization
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 lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>Dynamic Galton Board 2025</title> | |
| <style> | |
| :root { | |
| --bg: #0f172a; | |
| --peg: #94a3b8; | |
| --ball-color: #38bdf8; | |
| --board-w: 500px; | |
| --ball-size: 12px; | |
| } | |
| body { background: var(--bg); color: white; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; margin: 0; font-family: sans-serif; } | |
| .board { | |
| position: relative; | |
| width: var(--board-w); | |
| height: 600px; | |
| background: #1e293b; | |
| border: 6px solid #334155; | |
| border-radius: 12px; | |
| overflow: hidden; | |
| } | |
| /* Pegs */ | |
| .pegs { position: absolute; top: 40px; width: 100%; display: flex; flex-direction: column; align-items: center; } | |
| .row { display: flex; margin-bottom: 35px; } | |
| .peg { width: 6px; height: 6px; background: var(--peg); border-radius: 50%; margin: 0 25px; box-shadow: 0 0 4px var(--peg); } | |
| /* Bins */ | |
| .slots { position: absolute; bottom: 0; width: 100%; height: 120px; display: flex; border-top: 2px solid #475569; } | |
| .slot { flex: 1; border-right: 1px solid #334155; } | |
| /* Ball Visuals */ | |
| .ball { | |
| position: absolute; | |
| width: var(--ball-size); | |
| height: var(--ball-size); | |
| background: var(--ball-color); | |
| border-radius: 50%; | |
| top: -20px; | |
| left: calc(50% - (var(--ball-size) / 2)); | |
| opacity: 0; | |
| box-shadow: 0 0 8px var(--ball-color); | |
| animation: drop-animation 2.5s ease-in forwards; | |
| } | |
| @keyframes drop-animation { | |
| 0% { top: -20px; opacity: 1; } | |
| /* JavaScript will update --final-x and --final-y per ball */ | |
| 100% { top: var(--final-y); transform: translateX(var(--final-x)); opacity: 1; } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <h2>Galton Board: Dynamic Simulation</h2> | |
| <div class="board" id="galtonBoard"> | |
| <div class="pegs"> | |
| <div class="row"><div class="peg"></div></div> | |
| <div class="row"><div class="peg"></div><div class="peg"></div></div> | |
| <div class="row"><div class="peg"></div><div class="peg"></div><div class="peg"></div></div> | |
| <div class="row"><div class="peg"></div><div class="peg"></div><div class="peg"></div><div class="peg"></div></div> | |
| <div class="row"><div class="peg"></div><div class="peg"></div><div class="peg"></div><div class="peg"></div><div class="peg"></div></div> | |
| </div> | |
| <div class="slots"> | |
| <div class="slot"></div><div class="slot"></div><div class="slot"></div> | |
| <div class="slot"></div><div class="slot"></div><div class="slot"></div> | |
| <div class="slot"></div> | |
| </div> | |
| </div> | |
| <p>Simulating <span id="ballCount">0</span> balls. Change <code>totalBalls</code> in script to adjust.</p> | |
| <script> | |
| const totalBalls = 50; // CONTROL TOTAL BALLS HERE | |
| const board = document.getElementById('galtonBoard'); | |
| const countDisplay = document.getElementById('ballCount'); | |
| const ballSize = 14; | |
| const binCounts = [0, 0, 0, 0, 0, 0, 0]; // Track height for 7 bins | |
| countDisplay.innerText = totalBalls; | |
| function dropBall(index) { | |
| const ball = document.createElement('div'); | |
| ball.className = 'ball'; | |
| // Simulating 6 rows of pegs (Binomial Distribution) | |
| // Each "step" is a 50/50 chance to go left (-1) or right (+1) | |
| let position = 0; | |
| for (let i = 0; i < 6; i++) { | |
| position += Math.random() > 0.5 ? 1 : -1; | |
| } | |
| // Map position (-6 to 6) to one of the 7 bins (indexes 0 to 6) | |
| // Center position (0) maps to index 3 | |
| const binIndex = Math.min(Math.max(Math.round((position + 6) / 2), 0), 6); | |
| // Calculate final stacking position | |
| const finalX = (binIndex - 3) * 70; // 70px per bin offset from center | |
| const finalY = 585 - (binCounts[binIndex] * (ballSize - 2)); | |
| binCounts[binIndex]++; // Increase stack height for this bin | |
| ball.style.setProperty('--final-x', `${finalX}px`); | |
| ball.style.setProperty('--final-y', `${finalY}px`); | |
| ball.style.animationDelay = `${index * 0.4}s`; // Staggered drop | |
| board.appendChild(ball); | |
| } | |
| // Initialize simulation | |
| for (let i = 0; i < totalBalls; i++) { | |
| dropBall(i); | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment