Simple snow effect with canvas

Keywords: Front-end

First, create a new html file, set the background of the body to the dark blue of the sky, and create a canvas. The operation logic of canvas is put in snow.js:

<!DOCTYPE html>
<head>
  <style>
    body {
      background-color: #102a54;
    }
  </style>
</head>
<body>
  <canvas id='sky'></canvas>
  <script src="snow.js"></script>
</body>

</html>

The operation of canvas will be executed after the page is loaded. First, obtain the 2D context of canvas, and set the width and height of canvas to the width and height of window to ensure that the sky background covers the whole window. snow.js:

window.onload = function () {
  var canvas = document.getElementById('sky');
  var ctx = canvas.getContext('2d');

  var W = window.innerWidth;
  var H = window.innerHeight;
  canvas.width = W;
  canvas.height = H;
}

After the sky background is completed, we will create snowflakes. The idea is relatively simple. Let's keep a rated number of snowflakes on the screen, and give each snowflake a random location, random size and random falling speed:

  ...
  
  var flakesCount = 100; // Snowflake number
  var flakes = [];

  for (var i = 0; i < flakesCount; i++) {
    flakes.push({
      x: Math.random() * W, // Snowflake x-axis position
      y: Math.random() * H, // Snowflake y-axis position
      r: Math.random() * 5 + 2, // Radius of snowflake
      d: Math.random() + 1 // Snowflake density, used to control falling speed
    });
  }

Next, we need to draw these 100 snowflakes. For simplicity, we use small white circles to represent snowflakes:

  function drawFlakes() {
    ctx.clearRect(0, 0, W, H);
    ctx.fillStyle = '#fff';
    ctx.beginPath();
    for (var i = 0; i < flakesCount; i++) {
      var flake = flakes[i];
      console.log(flake);
      ctx.moveTo(flake.x, flake.y);
      ctx.arc(flake.x, flake.y, flake.r, 0, Math.PI * 2, true);
    }
    ctx.fill();
    moveFlakes(); // todo: snowflake fluttering effect
  }

After the snow painting is completed, we need to let the snow move and have the effect of falling. Our idea is to set a timer to re render canvas every 25ms. Each time we render, each snowflake moves down a certain distance. The higher the snowflake density, the faster the falling speed. And through the Math.sin function to create the effect of snowflakes fluttering around, when the snowflakes fall outside the window, move the snowflakes to the top of the window again and fall, as follows:

  var angle = 0;

  function moveFlakes() {
    angle += 0.01;
    for (var i = 0; i < flakesCount; i++) {
      var flake = flakes[i];
      flake.y += Math.pow(flake.d, 2) + 1; // The relationship between speed and density is not actually square, which is to make the effect more staggered
      flake.x += Math.sin(angle) * 2;

      if (flake.y > H) {
        flakes[i] = { x: Math.random() * W, y: 0, r: flake.r, d: flake.d };
      }
    }
  }

  setInterval(drawFlakes, 25);

Now, let's look at the actual effect:

You can also go to codepen : Snowing with canvas

Well, it's quite like that:)

Posted by ungovernable on Mon, 09 Dec 2019 16:01:50 -0800