The Falling Snow Effect

Yeah, I was thinking of making them a light blue. I copied all that but at the very beginning it just says Parsing error: Unexpected token < and nothing displays :frowning: Thatā€™s the same issue I was having before, even when I tried following someone elseā€™s step by step guide on how they did a similar snowflake animation.

Do you have a link to the page with the error? Iā€™d like to take a look at it in that errored state.

Edit:
I just tried the script on this siteā€™s home page, and copy/pasting seems to work. Letā€™s figure out what is going on in the Wix one.

I donā€™t think I canā€¦ I think itā€™s only accessible by logging onto my account and going into the web editor, which keeps any changes only visible to me until I publish the live version which the public can see.
I think Wix just uses a different way of coding, maybe? I tried Googling the parsing error thing and the only response was to make sure it was being placed in a HTML component rather than the site code or page source. Iā€™m not 100% sure what that means. Iā€™ve tried to create a snowflakeContainer box but it doesnā€™t give me an option to place separate coding for that. Iā€™m about to just have a simple gif running in the background instead lol

Wix may disallow custom HTML and JS outside of a small ā€œiframedā€ container for security reasons. I am not too familiar with Wixā€™s setup to know more. I did a quick google search, and I wasnā€™t able to find anything that seemed to help :frowning:

Edit:
For example, what is shown here may have the snow effect work only inside this small rectangular region and not throughout your entire page.

Thatā€™s alright, I appreciate your input anyway ^^ I really should pick up a web dev class or something so I know how to troubleshoot this kinda thing a little better.

Edit: Wait, that actually worked :open_mouth: But the snowflakes are only falling along the top.

It seems to be an iframe (for security reasons), so you canā€™t actually have the code interact with the larger page or even draw anything outside of its boundaries :frowning:

Love the snow effect.
I have it on a page now and it works great.
Can I change something in the code that will allow the page to be blank when you first arrive and then the snow begins falling immediately from the top?
Thank you for your thoughts.
Snow.

I am not in front of my computer to check, but try changing this line:

var initialYPos = getPosition(50, browserHeight);

This code is responsible for placing the snowflakes vertically on the page. To have it start from outside your viewable area, try this:

var initialYPos = getPosition(-50, -1 * browserHeight);

Let me know if this fixes it :slight_smile:

Thanks,
Kirupa

Thank you so much.
It works perfect.
Is there a way to change the snow flake to a .jpg pic?

Absolutely! What your snowflake looks like is controlled by this HTML:

<div id="snowflakeContainer">
  <span class="snowflake"></span>
</div>

You can replace the span element with an img element that points to a JPG file. Just be sure to retain the class value of snowflake on whatever element you replace the span with. Also, you may need to update the .snowflake style rule as part of it.

Cheers,
Kirupa

1 Like

Thank you for your help.
I have yet to try the .jpg bit.
I sure that it will work if I so decide to change it.
You are a big help.
Snow

1 Like

Is there a script to stop the animation after 30 or 60 seconds?

And thank you for creating this.

Do you want to both stop the animation and remove all existing snowflakes from the screen?

Can there be the option for both?

Stop the snow and it remains.

Or the snow stops falling from the top and the last of the snowflakes fall past the bottom of the screen?

Thank you!

To stop the animation, we just have to stop the animation loop from running. The following modification to the script shows how that can be done:

// Array to store our Snowflake objects
var snowflakes = [];

// Global variables to store our browser's window size
var browserWidth;
var browserHeight;

// Specify the number of snowflakes you want visible
var numberOfSnowflakes = 50;

// Flag to reset the position of the snowflakes
var resetPosition = false;

// Handle accessibility
var enableAnimations = false;
var reduceMotionQuery = matchMedia("(prefers-reduced-motion)");

// Handle animation accessibility preferences 
function setAccessibilityState() {
  if (reduceMotionQuery.matches) {
    enableAnimations = false;
  } else { 
    enableAnimations = true;
  }
}
setAccessibilityState();

reduceMotionQuery.addListener(setAccessibilityState);

//
// It all starts here...
//
function setup() {
  if (enableAnimations) {
    window.addEventListener("DOMContentLoaded", generateSnowflakes, false);
    window.addEventListener("resize", setResetFlag, false);
  }
}
setup();

//
// Constructor for our Snowflake object
//
function Snowflake(element, speed, xPos, yPos) {
  // set initial snowflake properties
  this.element = element;
  this.speed = speed;
  this.xPos = xPos;
  this.yPos = yPos;
  this.scale = 1;

  // declare variables used for snowflake's motion
  this.counter = 0;
  this.sign = Math.random() < 0.5 ? 1 : -1;

  // setting an initial opacity and size for our snowflake
  this.element.style.opacity = (.1 + Math.random()) / 3;
}

//
// The function responsible for actually moving our snowflake
//
Snowflake.prototype.update = function () {
  // using some trigonometry to determine our x and y position
  this.counter += this.speed / 5000;
  this.xPos += this.sign * this.speed * Math.cos(this.counter) / 40;
  this.yPos += Math.sin(this.counter) / 40 + this.speed / 30;
  this.scale = .5 + Math.abs(10 * Math.cos(this.counter) / 20);

  // setting our snowflake's position and size
  setTransform(Math.round(this.xPos), 
                Math.round(this.yPos), 
                this.scale, 
                this.element);

  // if snowflake goes below the browser window, move it back to the top
  if (this.yPos > browserHeight) {
    this.yPos = -50;
  }
}

//
// A performant way to set your snowflake's position
//
function setTransform(xPos, yPos, scale, el) {
  el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0) scale(${scale}, ${scale})`;
}

//
// The function responsible for creating the snowflake
//
function generateSnowflakes() {

  // get our snowflake element from the DOM and store it
  var originalSnowflake = document.querySelector(".snowflake");

  // access our snowflake element's parent container
  var snowflakeContainer = originalSnowflake.parentNode;
  snowflakeContainer.style.display = "block";

  var animationLoop = null;

  // get our browser's size
  browserWidth = document.documentElement.clientWidth;
  browserHeight = document.documentElement.clientHeight;

  // create each individual snowflake
  for (var i = 0; i < numberOfSnowflakes; i++) {

    // clone our original snowflake and add it to snowflakeContainer
    var snowflakeClone = originalSnowflake.cloneNode(true);
    snowflakeContainer.appendChild(snowflakeClone);

    // set our snowflake's initial position and related properties
    var initialXPos = getPosition(50, browserWidth);
    var initialYPos = getPosition(50, browserHeight);
    var speed = 5 + Math.random() * 40;

    // create our Snowflake object
    var snowflakeObject = new Snowflake(snowflakeClone,
      speed,
      initialXPos,
      initialYPos);
    snowflakes.push(snowflakeObject);
  }

  // remove the original snowflake because we no longer need it visible
  snowflakeContainer.removeChild(originalSnowflake);

  moveSnowflakes();
}

//
// Responsible for moving each snowflake by calling its update function
//
function moveSnowflakes() {

  if (enableAnimations) {
    for (var i = 0; i < snowflakes.length; i++) {
      var snowflake = snowflakes[i];
      snowflake.update();
    }      
  }

  // Reset the position of all the snowflakes to a new value
  if (resetPosition) {
    browserWidth = document.documentElement.clientWidth;
    browserHeight = document.documentElement.clientHeight;

    for (var i = 0; i < snowflakes.length; i++) {
      var snowflake = snowflakes[i];

      snowflake.xPos = getPosition(50, browserWidth);
      snowflake.yPos = getPosition(50, browserHeight);
    }

    resetPosition = false;
  }

  animationLoop = requestAnimationFrame(moveSnowflakes);
}

setTimeout(stopAnimation, 2000);

function stopAnimation() {
  cancelAnimationFrame(animationLoop);
}

//
// This function returns a number between (maximum - offset) and (maximum + offset)
//
function getPosition(offset, size) {
  return Math.round(-1 * offset + Math.random() * (size + 2 * offset));
}

//
// Trigger a reset of all the snowflakes' positions
//
function setResetFlag(e) {
  resetPosition = true;
}

To remove all the snowflakes once the animation ends, you can modify the stopAnimation function to be as follows:

function stopAnimation() {
  snowflakeContainer.parentNode.removeChild(snowflakeContainer);
  cancelAnimationFrame(animationLoop);
}

Let me know if this helps. I can dive deeper into any of this, so donā€™t hesitate to ask :slight_smile:

Cheers,
Kirupa

Thank you!

Hello, it helped me, there is a way to replace the balls with the ā€œLikeā€ button as the ā€œlikeā€ of facebook.

THANKS

Hi Brandon - absolutely! The snowflakes are just div elements. Place your like button image or HTML inside it. There are a bunch of CSS to make that div look like a circle, so remove that.

Let me know if you need any help with any part of this.

Cheers,
Kirupa :grinning:

What a beautiful snow effect, even after all these years!

Just a question, is there any reasonable way to make the amount of snowflakes responsive? I just want to have less snowflakes on mobile and more on desktops because of hardware constraints.

Yes! That can be easily accommodated in the current code. It is just about what value to set for:

var numberOfSnowflakes = 50;

Are you looking to set it only during page load depending on the size of the viewport, or do you want to adjust the number of snowflakes as part of someone resizing a window? My assumption is the former, but I wanted to double-check :slight_smile: