skip to Main Content

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


  1. 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():

    function createSnowflakes() {
        ...
    }
    
    const handle = setInterval(createSnowflakes, 1000);
    

    Notes:

    1. handle is need if you want to stop the effect (just call clearInterval(handle))
    2. that will trigger every 1000ms (=1s)
    3. if you want random/inconsistent timing, you should use setTimeout() instead:
      let keepMakingThem = true;
      function createSnowflakes() {
          ...
      
          if (keepMakingEm) {
              setTimeout(Math.random() * 1000);
          }
      }
      createSnowFlakes();
      

      (in this case, setting keepMakingThem to false will break the loop and make it stop – don’t do that with setInterval though)

    Login or Signup to reply.
  2. You should use SetInterval() read more here. Here’s a basic implementation. I also improved readability by using document.createElement and element.classList.add

    function createSnowflakes() {
        function create1Snowflake() {
          // document.body.innerHTML += `<div  class="snowflake${Math.floor(Math.random()*10)} snowflakes"></div>`;
          const snowflake = document.createElement("div")
          snowflake.classList.add(`snowflake${Math.floor(Math.random()*10)}`, "snowflakes")
          snowflake.style.transform = `translateX(${window.innerWidth * Math.random()}px)`;
          snowflake.style.animation = `falling1 ${Math.floor(Math.random() * 8)+3}s linear forwards`;
    
          snowflake.addEventListener('animationend', e => {
                snowflake.remove();
          })
          
          // add element to body
          document.body.appendChild(snowflake)
        }
        
      
        setInterval(() => {
          // make a snowflake
          create1Snowflake()
          
        }, 500)
    }
    
    createSnowflakes();
    

    To change how fast the snowflakes appear change the 500 inside of setInverval, but remember that it takes milliseconds not seconds.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search