I would like to add a particle system to a page that generates an appropriate number of particles based on the size of the screen. These particles must never fall outside the screen, but float over the current page.
Unfortunately, I have not been able to generate a nice transition of the particles, which is why I am now looking for help here. At the moment, a new position is simply calculated based on the current position by adjusting the coordinates by the size of the particle.
However, as I do this at a fixed interval, the entire system seems very robotic and not very nice, as the particles virtually teleport back and forth.
I have therefore tried to build the whole thing as HTML and thus tried to incorporate a few transitions with CSS, but that didn't help much either.
How do I set up my code so that the particles use a random image I have predefined and preferably don't need any HTML code but still fly nicely through the entire screen with different directions and generate a suitable number of particles based on the screen size?
I don't want a direction to be predefined and just bounce off the screen.
(() => {
const SIZE = 10;
const COUNT = 15;
let PARTICLES = [];
let INTERVAL = null;
const particles = document.getElementById('particles');
if (!particles) return;
const handleGeneration = _ => {
for (let i = 0; i < COUNT; i++) {
const particle = document.createElement('span');
particle.style.top = Math.floor(Math.random() * window.innerHeight) + 'px';
particle.style.left = Math.floor(Math.random() * window.innerWidth) + 'px';
particles.appendChild(particle);
PARTICLES.push(particle);
}
};
const handleMovement = _ => {
const parseRandom = _ => {
const random = Math.floor(Math.random() * 3);
switch (random) {
case 1:
return SIZE;
case 2:
return -SIZE;
default:
return random;
}
};
INTERVAL = setInterval(_ => {
PARTICLES.forEach((particle, index) => {
let top = parseInt(particle.style.top);
let left = parseInt(particle.style.left);
let directionTop = parseRandom();
let directionLeft = parseRandom();
if (top + directionTop < 0)
directionTop = SIZE;
else if (top + directionTop >= window.innerWidth - SIZE)
directionTop = -SIZE;
if (left + directionLeft < 0)
directionLeft = SIZE;
else if (left + directionLeft >= window.innerWidth - SIZE)
directionLeft = -SIZE;
particle.style.top = top + directionTop + 'px';
particle.style.left = left + directionLeft + 'px';
});
}, 125);
};
const handleResize = _ => {
window.addEventListener('resize', _ => {
PARTICLES.forEach(particle => particle.remove());
PARTICLES = [];
clearInterval(INTERVAL);
handleGeneration();
handleMovement();
});
window.dispatchEvent(new Event('resize'));
};
handleResize();
})();
#particles {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
opacity: .25;
}
#particles span {
position: absolute;
height: 10px;
width: 10px;
/* mask-repeat: no-repeat; */
/* mask-size: contain; */
/* mask-position: center; */
/* mask-image: url('../../Icons/square.svg'); */
transition: top 250ms linear, left 250ms linear;
}
#particles span:nth-child(odd) {
background-color: blue;
}
#particles span:nth-child(even) {
background-color: red;
}
<div id="particles"></div>
I find it best to use Math.sin() or Math.cos() to make objects move smoothly.