Generative Zen Garden
Home
Snippets
Generative Zen Garden
HTML
CSS
JS
<div class="ui">MOVE MOUSE TO DRAW</div> <canvas id="canvas"></canvas>
body { margin: 0; overflow: hidden; background: #1a1a1a; cursor: crosshair; } canvas { display: block; } .ui { position: fixed; top: 20px; left: 20px; color: #00CFA9; font-family: sans-serif; letter-spacing: 2px; pointer-events: none; }
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); let lines = []; function resize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } window.onresize = resize; resize(); class FlowLine { constructor(x, y) { this.x = x; this.y = y; this.history = []; this.angle = Math.random() * Math.PI * 2; this.life = 100; } update(mx, my) { const targetAngle = Math.atan2(my - this.y, mx - this.x); this.angle += (targetAngle - this.angle) * 0.1; this.x += Math.cos(this.angle) * 5; this.y += Math.sin(this.angle) * 5; this.history.push({x: this.x, y: this.y}); if (this.history.length > 20) this.history.shift(); this.life--; } draw() { ctx.beginPath(); ctx.strokeStyle = `rgba(0, 207, 169, ${this.life / 100})`; ctx.lineWidth = 2; ctx.moveTo(this.history[0]?.x || this.x, this.history[0]?.y || this.y); this.history.forEach(p => ctx.lineTo(p.x, p.y)); ctx.stroke(); } } let mouse = { x: window.innerWidth / 2, y: window.innerHeight / 2 }; window.onmousemove = (e) => { mouse.x = e.clientX; mouse.y = e.clientY; }; function animate() { ctx.fillStyle = 'rgba(26, 26, 26, 0.05)'; ctx.fillRect(0, 0, canvas.width, canvas.height); if (lines.length < 50) lines.push(new FlowLine(mouse.x, mouse.y)); lines.forEach((l, i) => { l.update(mouse.x, mouse.y); l.draw(); if (l.life <= 0) lines.splice(i, 1); }); requestAnimationFrame(animate); } animate();
Ad #1
Ad #2
Scroll to Top