htmlintermediatemitFeatured
Particle Field
A drifting field of connected particles.
4.8k1.9k655265
About this module
Particles drift slowly while nearby particles are connected with lines — the classic networking effect.
#canvas#2d#particles#connections#network
Source code
Installation
- 1
Create the files
Create `index.html`, `style.css` and `script.js` in the same folder.
- 2
Paste the code
Copy each file's source into its matching file.
- 3
Open in the browser
Open `index.html` in any modern browser.
Usage
- 1
Copy the HTML
Paste the canvas markup where you need it.
<link rel="stylesheet" href="style.css" /> <script src="script.js"></script> <div class="mh-canvas-wrap"> <canvas id="mh-canvas"></canvas> <span class="mh-canvas-label">PARTICLE FIELD</span> </div> - 2
Wire up the script
Include `script.js` before the closing body tag.
const canvas = document.getElementById("mh-canvas"); const ctx = canvas.getContext("2d"); let w, h, dpr = Math.min(window.devicePixelRatio || 1, 2); const CONFIG = { count: 90, linkDist: 120, speed: 0.35, color: "#818cf8" }; let parts = []; function resize() { const rect = canvas.parentElement.getBoundingClientRect(); w = rect.width; h = rect.height; canvas.width = w * dpr; canvas.height = h * dpr; canvas.style.width = w + "px"; canvas.style.height = h + "px"; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); parts = Array.from({ length: CONFIG.count }, () => ({ x: Math.random() * w, y: Math.random() * h, vx: (Math.random() - 0.5) * CONFIG.speed, vy: (Math.random() - 0.5) * CONFIG.speed })); } function tick() { ctx.clearRect(0, 0, w, h); for (const p of parts) { p.x += p.vx; p.y += p.vy; if (p.x < 0 || p.x > w) p.vx *= -1; if (p.y < 0 || p.y > h) p.vy *= -1; ctx.beginPath(); ctx.arc(p.x, p.y, 2, 0, Math.PI * 2); ctx.fillStyle = CONFIG.color; ctx.fill(); } for (let i = 0; i < parts.length; i++) { for (let j = i + 1; j < parts.length; j++) { const a = parts[i], b = parts[j]; const d = Math.hypot(a.x - b.x, a.y - b.y); if (d < CONFIG.linkDist) { ctx.beginPath(); ctx.moveTo(a.x, a.y); ctx.lineTo(b.x, b.y); ctx.strokeStyle = CONFIG.color; ctx.globalAlpha = (1 - d / CONFIG.linkDist) * 0.5; ctx.stroke(); ctx.globalAlpha = 1; } } } requestAnimationFrame(tick); } resize(); window.addEventListener("resize", resize); tick();