Rain Animation Effect with HTML5 Canvas, CSS and JavaScript | Sudden Evening Shower over Ohashi Bridge, Atake by Utagawa Hiroshige

03/03/2022

Demo

Full Screen

Video

YouTube Channel

Code

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Rain Animation Effect with HTML5 Canvas, CSS and JavaScript</title>
    <link rel="stylesheet" type="text/css" href="style.css">
  </head>
  <body>
    <div id="box">
      <canvas id="canvas" width="" height=""></canvas>
    </div>
    <script type="text/javascript" src="rain.js"></script>
  </body>
</html>

CSS

@charset "utf-8";
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
body {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
#box {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100vh;
  overflow: hidden;
  background-image: url(bg.png);
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
#canvas {
  transform: rotate(6deg);
}

JavaScript

let box = document.getElementById("box");
let canvas = document.getElementById("canvas");
let context = canvas.getContext("2d");

let drops,
    maxSpeed = 50,
    spacing = 5,
    xPosition,
    n;

function init() {
  canvas.width = box.clientWidth * 1.3;
  canvas.height = box.clientHeight * 1.3;

  drops = [];
  xPosition = 0;
  n = canvas.width / spacing;

  for (let i = 0; i < n; i++) {
    xPosition += spacing;
    drops.push({
      x: xPosition,
      y: Math.round(Math.random() * canvas.height),
      width: 1.2,
      height: Math.round(Math.random() * canvas.height),
      speed: Math.round(Math.random() * maxSpeed + 10),
    });
  }
}

function rain() {
  context.clearRect(0, 0, canvas.width, canvas.height);
  for (let i = 0; i < n; i++){
    context.fillStyle = "#2e2f1d";
    context.fillRect(drops[i].x, drops[i].y, drops[i].width, drops[i].height);
    drops[i].y += drops[i].speed;

    if (drops[i].y > canvas.height) {
      drops[i].y = 0 - drops[i].height;
    }
  }
  requestAnimationFrame(rain);
}

function main() {
  init();
  rain();
}

window.addEventListener('load', main, false);
window.addEventListener('resize', init, false);