JSFiddle - React, Tailwind, and code Playground

by Сергей Тарасевич

HTML

<div id="container">
    <canvas id="waterfall"></canvas>
</div>

CSS

body {
    background: #222;
    margin:0;
    padding:0;
}
#container {
    height: 0;
    position: absolute;
    width: 100%;
}
canvas {
    display: block;
    margin: 0 auto;
}

JavaScript

var waterfallCanvas = function (c, cw, ch) {

    var _this = this;
    this.c = c;
    this.ctx = c.getContext('2d');
    this.cw = cw;
    this.ch = ch;

    this.particles = [];
    this.particleRate = 6;
    this.gravity = .15;


    this.init = function () {
        this.loop();
    };

    this.reset = function () {
        this.ctx.clearRect(0, 0, this.cw, this.ch);
        this.particles = [];
    };

    this.rand = function (rMi, rMa) {
        return~~ ((Math.random() * (rMa - rMi + 1)) + rMi);
    };


    this.Particle = function () {
        var newWidth = _this.rand(1, 20);
        var newHeight = _this.rand(1, 45);
        this.x = _this.rand(10 + (newWidth / 2), _this.cw - 10 - (newWidth / 2));
        this.y = -newHeight;
        this.vx = 0;
        this.vy = 0;
        this.width = newWidth;
        this.height = newHeight;
        this.hue = _this.rand(200, 220);
        this.saturation = _this.rand(30, 60);
        this.lightness = _this.rand(30, 60);
    };

    this.Particle.prototype.update = function (i) {
        this.vx += this.vx;
        this.vy += _this.gravity;
        this.x += this.vx;
        this.y += this.vy;
    };

    this.Particle.prototype.render = function () {
        _this.ctx.strokeStyle = 'hsla(' + this.hue + ', ' + this.saturation + '%, ' + this.lightness + '%, .05)';
        _this.ctx.beginPath();
        _this.ctx.moveTo(this.x, this.y);
        _this.ctx.lineTo(this.x, this.y + this.height);
        _this.ctx.lineWidth = this.width / 2;
        _this.ctx.lineCap = 'round';
        _this.ctx.stroke();
    };

    this.Particle.prototype.renderBubble = function () {
        _this.ctx.fillStyle = 'hsla(' + this.hue + ', 40%, 40%, 1)';
        _this.ctx.fillStyle = 'hsla(' + this.hue + ', ' + this.saturation + '%, ' + this.lightness + '%, .3)';
        _this.ctx.beginPath();
        _this.ctx.arc(this.x + this.width / 2, _this.ch - 20 - _this.rand(0, 10), _this.rand(1, 8), 0, Math.PI * 2, false);
       ...