SnowFall in Canvas

100 flakes with different sizes fly in chaotic Brownian motion.

by spmbt

HTML

<title>SnowFall. Version with snow melting</title>
<canvas id="canvas" width="1396" height="561"></canvas><br>
<button>Toggle Motion</button>

CSS

canvas#canvas{background-image: url("https://habrastorage.org/files/bec/373/8a0/bec3738a036b43199a84de8da47933bc.jpg");}

JavaScript

'use strict';
    var canvas = document.getElementById('canvas')
    ,interv = 30
    ,Snowflake = function(h){
        this.width = canvas.width;
        this.height = canvas.height;
        this.vxCommon = .004;
        this.vyCommon = .0226;
        this.r = h.r;
        this.parallax = h.parallax;
        this.x = h.x;
        this.y = h.y;
        this.vx = h.vx;
        this.vy = h.vy;
        this.vMelt = .993;
    };
    Snowflake.prototype = {
        rMin: 1.8
        ,rMax: 5
        ,plain: .88 * canvas.height //level of plain when flakes are stops
    };
    var rand = function(n, shift){return (shift!=null ? shift : -n/2) + n * Math.random();}
    ,randRad
    ,snowflakes = Array.apply(0, Array(120)).map(function(){return new Snowflake({
        r: randRad = rand(Snowflake.prototype.rMax, Snowflake.prototype.rMin)
        ,parallax: randRad *.005
        ,x: rand(canvas.width - 2* randRad, randRad)
        ,y: rand(canvas.height  - 2* randRad, randRad - (canvas.height - Snowflake.prototype.plain))
        ,vx: rand(.02)
        ,vy: rand(.02)
    });})
    ,cont = canvas.getContext('2d'), noStopMotion =1, count=0;
    cont.fillStyle = 'rgba(170, 177, 205, 0.29)';
    cont.fillRect(0, 0, canvas.width, canvas.height);
    cont.fillStyle = 'rgba(185, 196, 207, 0.78)';

    var startMotion = function(dt2, base_image){ //render all
        var now = +new Date();
        cont.clearRect(0, 0, canvas.width, canvas.height);

        snowflakes.forEach(function(S, i, arr){ //render flake
            S.date = S.date || now;
            var dt = dt2 || now - S.date;
            if(!(S.y > S.plain - 2 * S.r -2 + (S.r - S.rMin) * (S.height - S.plain) / (S.rMax - S.rMin) )){
                S.x += dt * (S.vx + S.vxCommon + S.parallax);
                S.x -= S.width * (S.x / S.width | 0);
                S.y += dt * (S.vy + S.vyCommon + S.parallax);
                S.y -= S.height * (S.y / S.height | 0);
                S.vx = (S.vx + rand(.002)) * .999;
         ...