So I wanted to make a simple effect of snowflakes falling from the sky randomly. I can make them all fall at the same time with different velocities, but i cant seem to call for a while loop again only for +1 snowflake. Here is the link for the whole thing to give u an idea of what it should look like
Here is the code:
function createSnowflakes() {
let i = 0;
while (i < 30) {
document.body.innerHTML += `<div class="snowflake${Math.floor(Math.random()*10)} snowflakes"></div>`;
i++
}
let snowflakes = document.querySelectorAll('.snowflakes');
snowflakes.forEach((snowflake) => {
snowflake.style.transform = `translateX(${window.innerWidth * Math.random()}px)`;
snowflake.style.animation = `falling1 ${Math.floor(Math.random() * 8)+3}s linear forwards`;
})
snowflakes.forEach((elem) => console.log(elem));
snowflakes.forEach((elem) => {
elem.addEventListener('animationend', e => {
elem.remove();
snowflakes = document.querySelectorAll('.snowflakes');
if (snowflakes.length < 10) {
createSnowflakes();
}
})
})
}
createSnowflakes();
2
Answers
A naive infinite loop in javascript will typically cause the browser to lock up.
Additionally, it will not render correctly – it will look like it is skipping frames (since rendering is only done in the end). There is an API that makes that possible: requestAnimationFrame. While it doesn’t look like an infinite loop, that is what it does in practice (when you keep calling it).
However, looking at your code, you don’t seem to need an infinite loop at all, but rather to trigger your snowmaker every few (milli)seconds – which can be done with
setInterval()
:Notes:
handle
is need if you want to stop the effect (just callclearInterval(handle)
)setTimeout()
instead:(in this case, setting
keepMakingThem
to false will break the loop and make it stop – don’t do that withsetInterval
though)You should use
SetInterval()
read more here. Here’s a basic implementation. I also improved readability by usingdocument.createElement
andelement.classList.add
To change how fast the snowflakes appear change the 500 inside of
setInverval
, but remember that it takes milliseconds not seconds.