1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Happy Lantern Festival</title> <style> html, body, canvas { width: 100%; height: 100%; margin: 0; } body { overflow: hidden; background: #10051e; } h1 { position: fixed; inset: 1.5rem 0 auto; z-index: 1; margin: 0; color: #ffd86b; text-align: center; font-family: system-ui, sans-serif; } </style> </head> <body> <h1>Happy Lantern Festival</h1> <canvas id="scene"></canvas> <script> const canvas = document.querySelector("#scene"); const ctx = canvas.getContext("2d"); const lanterns = Array.from({ length: 24 }, () => ({ x: Math.random(), y: Math.random(), size: 12 + Math.random() * 18, speed: .00002 + Math.random() * .00004 }));
function resize() { const ratio = devicePixelRatio || 1; canvas.width = innerWidth * ratio; canvas.height = innerHeight * ratio; ctx.setTransform(ratio, 0, 0, ratio, 0, 0); }
function frame(time) { ctx.clearRect(0, 0, innerWidth, innerHeight); for (const light of lanterns) { light.y = (light.y - light.speed * 16 + 1) % 1; const x = light.x * innerWidth + Math.sin(time / 900 + light.x * 8) * 10; const y = light.y * innerHeight; ctx.shadowBlur = 18; ctx.shadowColor = "#ff9a35"; ctx.fillStyle = "#ef4938"; ctx.fillRect(x, y, light.size, light.size * 1.25); } requestAnimationFrame(frame); } addEventListener("resize", resize); resize(); requestAnimationFrame(frame); </script> </body> </html>
|