JSFiddle - React, Tailwind, and code Playground
by fgnass
HTML
<div id="container"></div>
CSS
html,
body {
background: #252525;
}
JavaScript
var NUM_PARTICLES = ((ROWS = 20) * (COLS = 20)),
THICKNESS = Math.pow(60, 2),
SPACING = 20,
MARGIN = 100,
COLOR = 220,
DRAG = 0.95,
EASE = 0.25,
canvas,
mouse,
list,
ctx,
dx, dy,
mx, my,
d, t, f,
a, b,
i, n,
w, h,
p, s,
r, c;
function init() {
container = document.getElementById('container');
canvas = document.createElement('canvas');
ctx = canvas.getContext('2d');
list = [];
w = canvas.width = COLS * SPACING + MARGIN * 2;
h = canvas.height = ROWS * SPACING + MARGIN * 2;
for (i = 0; i < NUM_PARTICLES; i++) {
p = {
vx: 0,
vy: 0,
x: 0,
y: 0
};
p.x = p.ox = MARGIN + SPACING * (i % COLS);
p.y = p.oy = MARGIN + SPACING * Math.floor(i / COLS);
list[i] = p;
}
container.addEventListener('pointermove', function(e) {
const bounds = container.getBoundingClientRect();
mx = e.clientX - bounds.left;
my = e.clientY - bounds.top;
});
container.appendChild(canvas);
ctx.fillStyle = "#5B5B5B";
}
function step() {
for (i = 0; i < NUM_PARTICLES; i++) {
p = list[i];
d = (dx = mx - p.x) * dx + (dy = my - p.y) * dy;
f = -THICKNESS / d;
if (d < THICKNESS) {
t = Math.atan2(dy, dx);
p.vx += f * Math.cos(t);
p.vy += f * Math.sin(t);
}
p.x += (p.vx *= DRAG) + (p.ox - p.x) * EASE;
p.y += (p.vy *= DRAG) + (p.oy - p.y) * EASE;
}
ctx.clearRect(0, 0, w, h);
for (i = 0; i < NUM_PARTICLES; i++) {
p = list[i];
ctx.fillRect(p.x, p.y, 2, 2);
}
requestAnimationFrame(step);
}
init();
step();