canvas = {
const minDistance2 = minDistance * minDistance;
const maxDistance2 = maxDistance * maxDistance;
const context = DOM.context2d(width, height);
let c = this || DOM.context2d(width, height);
if (stop) return yield c;
while (true) {
context.save();
context.clearRect(0, 0, width, height);
for (let i = 0; i < n; ++i) {
const p = particles[i];
p.x += p.vx;
if (p.x < -maxDistance) p.x += width + maxDistance * 2;
else if (p.x > width + maxDistance) p.x -= width + maxDistance * 2;
p.y += p.vy;
if (p.y < -maxDistance) p.y += height + maxDistance * 2;
else if (p.y > height + maxDistance) p.y -= height + maxDistance * 2;
// that is close to the current one (see plots below).
p.vx += 0.2 * (Math.random() - 0.5) - 0.01 * p.vx;
p.vy += 0.2 * (Math.random() - 0.5) - 0.01 * p.vy;
// Draw the particle
context.beginPath();
context.arc(p.x, p.y, radius, 0, 2 * Math.PI);
context.fill();
}
// Work on the particle connections. Check one particle against all the
// other ones.
for (let i = 0; i < n; ++i) {
for (let j = i + 1; j < n; ++j) {
// get the two particles we are going to work on (pi, pj)
const pi = particles[i];
const pj = particles[j];
// compute their distance
const dx = pi.x - pj.x;
const dy = pi.y - pj.y;
const d2 = dx * dx + dy * dy;
// if the particles are close enough connect them an give them an opacity
if (d2 < maxDistance2) {
const a =
d2 > minDistance2
? (maxDistance2 - d2) / (maxDistance2 - minDistance2)
: 1;
context.globalAlpha = a;
context.beginPath();
context.moveTo(pi.x, pi.y);
context.lineTo(pj.x, pj.y);
context.stroke();
if (false) {
console.log(
`d2:${d2.toFixed(
1
)} < max2:${maxDistance2} -> min2:${minDistance2}: a:${a.toFixed(
1
)} (${pi.x.toFixed(0)},${pi.y.toFixed(0)}) (${pj.x.toFixed(
0
)},${pj.y.toFixed(0)})`
);
}
}
}
}
context.restore();
yield context.canvas;
await Promises.delay(delayms);
}
}