Created
March 17, 2026 12:42
-
-
Save CrazybutSolid/c15d7bd6a6877e32c41925a7538b8a64 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> | |
| <head> | |
| <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"> | |
| <meta name="apple-mobile-web-app-capable" content="yes"> | |
| <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> | |
| <title>White Noise</title> | |
| <link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400&display=swap" rel="stylesheet"> | |
| <style> | |
| * { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; } | |
| html, body { width: 100%; height: 100%; } | |
| body { | |
| font-family: 'DM Sans', sans-serif; | |
| background: #0d1117; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| height: 100vh; | |
| min-height: 500px; | |
| overflow: hidden; | |
| user-select: none; | |
| } | |
| .ambient { | |
| position: absolute; | |
| inset: 0; | |
| overflow: hidden; | |
| pointer-events: none; | |
| } | |
| .orb { | |
| position: absolute; | |
| border-radius: 50%; | |
| filter: blur(80px); | |
| opacity: 0; | |
| transition: opacity 2s ease; | |
| } | |
| .orb1 { width: 400px; height: 400px; background: #1a3a5c; top: -100px; left: -100px; } | |
| .orb2 { width: 350px; height: 350px; background: #0d2d1f; bottom: -80px; right: -80px; } | |
| .orb3 { width: 300px; height: 300px; background: #1f1040; top: 50%; left: 50%; transform: translate(-50%,-50%); } | |
| body.playing .orb { opacity: 1; } | |
| .ripple-container { | |
| position: absolute; | |
| inset: 0; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| pointer-events: none; | |
| } | |
| .ripple { | |
| position: absolute; | |
| width: 200px; | |
| height: 200px; | |
| border-radius: 50%; | |
| border: 1px solid rgba(100, 180, 255, 0.15); | |
| opacity: 0; | |
| } | |
| body.playing .ripple { | |
| animation: rippleOut 3s ease-out infinite; | |
| } | |
| .ripple:nth-child(2) { animation-delay: 1s !important; } | |
| .ripple:nth-child(3) { animation-delay: 2s !important; } | |
| @keyframes rippleOut { | |
| 0% { transform: scale(1); opacity: 0.5; } | |
| 100% { transform: scale(3.5); opacity: 0; } | |
| } | |
| .content { | |
| position: relative; | |
| z-index: 10; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 40px; | |
| } | |
| .label-top { | |
| font-size: 11px; | |
| letter-spacing: 0.25em; | |
| text-transform: uppercase; | |
| color: rgba(255,255,255,0.25); | |
| transition: color 1s ease; | |
| } | |
| body.playing .label-top { color: rgba(255,255,255,0.45); } | |
| .btn-wrap { | |
| position: relative; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .btn { | |
| width: 160px; | |
| height: 160px; | |
| border-radius: 50%; | |
| border: 1px solid rgba(255,255,255,0.1); | |
| background: rgba(255,255,255,0.04); | |
| cursor: pointer; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 10px; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .btn::before { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| border-radius: 50%; | |
| background: radial-gradient(circle at 40% 35%, rgba(255,255,255,0.07), transparent 65%); | |
| } | |
| .btn:active { transform: scale(0.95); } | |
| body.playing .btn { | |
| border-color: rgba(100, 180, 255, 0.3); | |
| background: rgba(100, 180, 255, 0.06); | |
| box-shadow: 0 0 40px rgba(100, 180, 255, 0.08), inset 0 0 30px rgba(100, 180, 255, 0.04); | |
| } | |
| .icon { | |
| width: 32px; | |
| height: 32px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .play-icon { display: flex; } | |
| .stop-icon { display: none; } | |
| body.playing .play-icon { display: none; } | |
| body.playing .stop-icon { display: flex; } | |
| .btn-label { | |
| font-size: 11px; | |
| letter-spacing: 0.15em; | |
| text-transform: uppercase; | |
| color: rgba(255,255,255,0.4); | |
| font-weight: 300; | |
| transition: color 0.3s; | |
| } | |
| body.playing .btn-label { color: rgba(100, 180, 255, 0.7); } | |
| .volume-section { | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| gap: 12px; | |
| width: 200px; | |
| } | |
| .vol-label { | |
| font-size: 10px; | |
| letter-spacing: 0.2em; | |
| text-transform: uppercase; | |
| color: rgba(255,255,255,0.2); | |
| } | |
| input[type=range] { | |
| -webkit-appearance: none; | |
| width: 100%; | |
| height: 2px; | |
| background: rgba(255,255,255,0.1); | |
| border-radius: 2px; | |
| outline: none; | |
| cursor: pointer; | |
| } | |
| input[type=range]::-webkit-slider-thumb { | |
| -webkit-appearance: none; | |
| width: 14px; | |
| height: 14px; | |
| border-radius: 50%; | |
| background: rgba(255,255,255,0.5); | |
| cursor: pointer; | |
| transition: background 0.2s; | |
| } | |
| body.playing input[type=range]::-webkit-slider-thumb { | |
| background: rgba(100, 180, 255, 0.8); | |
| } | |
| input[type=range]::-webkit-slider-runnable-track { | |
| height: 2px; | |
| border-radius: 2px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="ambient"> | |
| <div class="orb orb1"></div> | |
| <div class="orb orb2"></div> | |
| <div class="orb orb3"></div> | |
| </div> | |
| <div class="ripple-container"> | |
| <div class="ripple"></div> | |
| <div class="ripple"></div> | |
| <div class="ripple"></div> | |
| </div> | |
| <div class="content"> | |
| <div class="label-top">white noise</div> | |
| <div class="btn-wrap"> | |
| <button class="btn" id="btn" onclick="toggle()"> | |
| <div class="icon play-icon"> | |
| <svg width="24" height="24" viewBox="0 0 24 24" fill="none"> | |
| <polygon points="7,4 20,12 7,20" fill="rgba(255,255,255,0.6)"/> | |
| </svg> | |
| </div> | |
| <div class="icon stop-icon"> | |
| <svg width="22" height="22" viewBox="0 0 22 22" fill="none"> | |
| <rect x="3" y="3" width="6" height="16" rx="1.5" fill="rgba(100,180,255,0.8)"/> | |
| <rect x="13" y="3" width="6" height="16" rx="1.5" fill="rgba(100,180,255,0.8)"/> | |
| </svg> | |
| </div> | |
| <span class="btn-label" id="btn-label">play</span> | |
| </button> | |
| </div> | |
| <div class="volume-section"> | |
| <span class="vol-label">volume</span> | |
| <input type="range" id="vol" min="0" max="100" value="70" oninput="setVolume(this.value)"> | |
| </div> | |
| </div> | |
| <script> | |
| let ctx, source, gainNode, playing = false; | |
| function toggle() { | |
| if (!playing) { | |
| ctx = new (window.AudioContext || window.webkitAudioContext)(); | |
| const bufSize = ctx.sampleRate * 4; | |
| const buf = ctx.createBuffer(2, bufSize, ctx.sampleRate); | |
| for (let ch = 0; ch < 2; ch++) { | |
| const d = buf.getChannelData(ch); | |
| for (let i = 0; i < bufSize; i++) d[i] = Math.random() * 2 - 1; | |
| } | |
| source = ctx.createBufferSource(); | |
| source.buffer = buf; | |
| source.loop = true; | |
| gainNode = ctx.createGain(); | |
| gainNode.gain.value = document.getElementById('vol').value / 100; | |
| source.connect(gainNode); | |
| gainNode.connect(ctx.destination); | |
| source.start(); | |
| playing = true; | |
| document.body.classList.add('playing'); | |
| } else { | |
| gainNode.gain.setTargetAtTime(0, ctx.currentTime, 0.3); | |
| setTimeout(() => { source.stop(); ctx.close(); }, 400); | |
| playing = false; | |
| document.body.classList.remove('playing'); | |
| } | |
| } | |
| function setVolume(v) { | |
| if (gainNode) gainNode.gain.setTargetAtTime(v / 100, ctx.currentTime, 0.05); | |
| } | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment