JS-E03 - Efeito Neve (snow) com JavaScript

JS-E03 - Efeito Neve (snow) com JavaScript
Publicado em 25/01/2021 21h22
Visualizações: 690

Aprenda a realizar o efeito de neve de forma descomplicada

Este é um efeito que coloquei na home desta página, para dar colocar um algo a mais no "call to action".

A imagem que utilizo de fundo tem tons de magenta, então escolhi este tom para os flocos em movimento.

JS-E03 - Efeito Neve (snow) com JavaScript

O código é levemente complexo, mas é bem prático de configurar, e utilizei um macete para permitir que os flocos partissem também do bottom desta seção.

O função em JS, declarada como variável é a seguinte:

//EFEITO SNOW
let snowCanvas = function (obj) {
    var canvas = obj.el;

    canvas.style.backgroundColor = obj.background;
    var fillStyle = obj.snowColor;
    var ctx = canvas.getContext("2d");

    var maxSpeed = obj.maxSpeed,
    minSpeed = obj.minSpeed,
    count = obj.amount ,
    rMax = obj.rMax,
    rMin = obj.rMin,
    W, H; //height and width of canvas;
    setHeightWidth( );

    function setHeightWidth( ) {
        W = obj.width;
        H = obj.height;
        canvas.width = W;
        canvas.height = H;
    }

    window.onresize = setHeightWidth;

    var snowGroup = [];
    var i;
    for (i = 0; i < count; i++) {
        snowGroup.push(initialEverySnow());
    }

    function initialEverySnow() {
        return {
        x: Math.random() * W - rMax,
        y: Math.random() * H - rMax,
        r: Math.random() * (rMax - rMin) + rMin,
        s: Math.random() * (maxSpeed - minSpeed) + minSpeed,
        xChangeRate: Math.random() * 1.6 - 0.8
        };
    }

    function draw() {
        ctx.clearRect(0, 0, W, H);
        ctx.beginPath();

        var p;
        for (var i = 0; i < snowGroup.length; i++) {
            p = snowGroup[i];
            ctx.fillStyle = fillStyle;
            ctx.moveTo(p.x, p.y);
            ctx.arc(p.x, p.y, p.r, 0, 2 * Math.PI);
        }
        ctx.fill();
        update();
    }

    var delta = 0;
    function update() {
        //update position of every snow
        delta += 0.01;
        var p;
        for (var i = 0; i < snowGroup.length; i++) {
            p = snowGroup[i];
            p.y += p.s;
            p.x += Math.sin(delta + p.xChangeRate) * p.xChangeRate;
            if (p.x > W + p.r || p.y > H + p.r || p.x < -p.r) {
                snowGroup[i] = initialEverySnow();
                var randomStartPostion = Math.ceil(Math.random() * 3);
                switch (randomStartPostion) {
                    case 1:
                    //drop from top
                    snowGroup[i].x = Math.random() * W;
                    snowGroup[i].y = -rMax;
                    break;
                    case 2:
                    //start from left
                    snowGroup[i].x = -rMax;
                    snowGroup[i].y = Math.random() * H;
                    break;
                    case 3:
                    //start from right
                    snowGroup[i].x = W + rMax;
                    snowGroup[i].y = Math.random() * H;
                    break;
                }
            }
        }
    }
    setInterval(draw, 1000 / 60);
};

Para acionar utilizei a seguinte função, passando os parâmtros necessários para a função snowCanvas, que será aplicada em um elemento canvas, selecionado através de um id. Implementei uma condicional por utilizar um único script minificado para a camada web desta página:

if (document.getElementById("snowCanvas")) {
    window.onload = snowCanvas({
        el: document.getElementById("snowCanvas"), // elemento selecionado
        snowColor: "#821C87", // cor dos flocos
        background: "rgba(0,0,0,0)", // cor de fundo que deixei trasnparente para apresentar a minha imagem
        maxSpeed: 2, // velocidade máxima do movimento
        minSpeed: 1, // velocidade mínima do movimento
        width: "", // largura opicional
        height: "", // altura opicional
        amount: 15, // quantidade de flocos
        rMax: 4, // raio máximo do floco
        rMin: 1 // raio mínimo do floco
    });
}

No html, basta utilizar o canvas com o id "snowCanvas". Eu utilizei na página home deste site a tag canvas da seguinte forma:

JS-E03 - Efeito Neve (snow) com JavaScript

Percebeu que utilizei dois elementos canvas? Agora vem um macete! O segundo canvas foi utilizado para implementar os flocos subindo, poderia ser utilizado para qualquer lado, inlcuindo um evento de mouseMove alterando a orientação deste elemento.

Na ativação eu dupliquei a chamada do método snowCanvas passando os elementos canvas pelos seus respectivos id (snowCanvas e snowCanvas2):

if (document.getElementById("snowCanvas1")) {
    window.onload = snowCanvas({
        el: document.getElementById("snowCanvas"),
        snowColor: "#821C87",
        background: "rgba(0,0,0,0)",
        maxSpeed: 2,
        minSpeed: 1,
        width: "",
        height: "",
        amount: 15,
        rMax: 4,
        rMin: 1
    });
}

if (document.getElementById("snowCanvas2")) {
    window.onload = snowCanvas({
        el: document.getElementById("snowCanvas2"),
        snowColor: "#821C87",
        background: "rgba(0,0,0,0)",
        maxSpeed: 2,
        minSpeed: 1,
        width: "",
        height: "",
        amount: 15,
        rMax: 4,
        rMin: 1
    });
}

utilizei as mesmas cores, mas podem ser utilizadas n cores, tomando cuidado com a performance.

Para inverter o sentido do floco, rotacionei este canvas em 180graus no css:

#snowCanvas1, #snowCanvas2 {
    top: 0;
    left: 0;
    position: absolute;
    max-width: 100%;
    overflow-x: hidden;
}

#snowCanvas1{
    z-index: 1;
}

#snowCanvas2{
    z-index: 2;
    transform: rotate(180deg);
}

 

Utilizei o z-index para sobrepor os elementos, colocando como absolute à div pai. O botão eu defini com o z-index 4 e no mobile defini o nav com 5, sobrepondo corretamente os elementos.

Caso seja necessário apenas o efeito simples, basta inserir o canvas definindo altura e largura, com uma cor de fundo que destaque os flocos.

Para visualizar o efeito, clique aqui na HOME.

 

Veja também:

Confira mais artigos relacionados

Este website utiliza cookies próprios e de terceiros a fim de personalizar o conteúdo, melhorar a experiência do usuário, fornecer funções de mídias sociais e analisar o tráfego. Para continuar navegando você deve concordar com nossa Política de Privacidade

Sim, eu aceito. Não, eu não aceito.