htmlintermediatemit
Mouse Trail Particles
Particles that chase the cursor.
6.5k1.8k278488
About this module
A swarm of particles that accelerates toward the mouse position, creating an organic trail.
#canvas#2d#particles#mouse#interactive
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">MOVE YOUR CURSOR</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 mouse = { x: 0, y: 0, active: false }; const CONFIG = { count: 70, speed: 0.06, color: "#22d3ee" }; 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: 0, vy: 0 })); } function tick() { ctx.clearRect(0, 0, w, h); for (const p of parts) { const dx = (mouse.active ? mouse.x : w / 2) - p.x; const dy = (mouse.active ? mouse.y : h / 2) - p.y; p.vx += dx * CONFIG.speed; p.vy += dy * CONFIG.speed; p.vx *= 0.88; p.vy *= 0.88; 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(); } requestAnimationFrame(tick); } canvas.addEventListener("mousemove", (e) => { const r = canvas.getBoundingClientRect(); mouse.x = e.clientX - r.left; mouse.y = e.clientY - r.top; mouse.active = true; }); canvas.addEventListener("mouseleave", () => { mouse.active = false; }); resize(); window.addEventListener("resize", resize); tick();