This is fun. One suggestion.. rather than creating a canvas for each user using a querySelectorAll and a loop, I'd use an IntersectionObserver and only create the canvases as they scroll into view. That way the user's device won't need to create hundreds of elements when the code runs. let observer = new IntersectionObserver( (entries) => { entries.forEach((entry, i) => { if (entry.isIntersecting) { const p = 2; cons…
x.fillStyle = '#' + ((r >> 8) & 0xffffff).toString(16).padStart(0, 6);
to: x.fillStyle = '#' + ((r >> 8) & 0xffffff).toString(16).padStart(6, '0');
as the pad target length is the first parameter of padStart.