Lab / 25 min build
Magnetic dot grid
A quiet grid of dots that bends and warms up wherever the pointer goes.
The core
// A grid of dots, each remembering its home position.
export function makeGrid(w, h, gap) {
const dots = [];
for (let y = gap / 2; y < h; y += gap)
for (let x = gap / 2; x < w; x += gap)
dots.push({ hx: x, hy: y, x, y });
return dots;
}
// Dots near the pointer are pulled toward it, then ease back home.
// `pull` is how far they travel, as a share of the distance to the pointer.
export function attract(dots, pointer, radius, pull = 0.35) {
for (const d of dots) {
const dx = pointer.x - d.hx, dy = pointer.y - d.hy;
const dist = Math.hypot(dx, dy);
const k = dist < radius ? (1 - dist / radius) ** 2 * pull : 0;
const tx = d.hx + dx * k, ty = d.hy + dy * k;
d.x += (tx - d.x) * 0.18;
d.y += (ty - d.y) * 0.18;
d.k = k / pull; // 0 at rest, 1 under the pointer
}
}How it works
- Lay out the grid. Every dot stores its home position. The gap scales with the screen so phones and desktops get roughly the same number of dots per row.
- Pull toward the pointer. Within a radius, a dot’s target moves part of the way toward the pointer. Squaring the falloff keeps the edge of the effect soft.
- Ease, don’t snap. Each frame the dot covers 18% of the remaining distance to its target, so it glides in and glides back.
- Show the strength. The same pull value drives size and color, from grey at rest through violet and pink to orange under the pointer.
- Idle motion. With no pointer, a hidden attractor drifts on a slow loop. That is what the reel records.
Full source
Get the whole project as a zip
The demo page, every file and the export settings for the reel. It lands in your inbox, along with one new build a week.
You'll get a confirmation email first. One click to unsubscribe.
Make reels like this one
Reel Engine
The render pipeline behind every reel: HTML to MP4 at 1080×1920, 10 effects, 9:16 templates and a setup guide.