Explicação:


2. Estilizando o Canvas com CSS

Vamos adicionar um estilo simples para dar à nossa tela um fundo preto e garantir que todo o preenchimento e margens sejam removidos.

* {    margin: 0;    padding: 0;    box-sizing: border-box;}canvas {    background-color: black;}

Explicação:


3. Classe de Partículas: Criando a Magia

A classe Particle é onde está o núcleo da animação. Cada partícula se move pela tela, deixando um rastro de suas localizações anteriores, criando o efeito de fluxo.

class Particle {    constructor(effect) {        this.effect = effect;        this.x = Math.floor(Math.random() * this.effect.width);        this.y = Math.floor(Math.random() * this.effect.height);        this.speedModifier = Math.floor(Math.random() * 5   1);        this.history = [{ x: this.x, y: this.y }];        this.maxLength = Math.floor(Math.random() * 200   10);        this.timer = this.maxLength * 2;        this.colors = [\\'#4C026B\\', \\'#8E0E00\\', \\'#9D0208\\', \\'#BA1A1A\\', \\'#730D9E\\'];        this.color = this.colors[Math.floor(Math.random() * this.colors.length)];    }    draw(context) {        context.beginPath();        context.moveTo(this.history[0].x, this.history[0].y);        for (let i = 1; i < this.history.length; i  ) {            context.lineTo(this.history[i].x, this.history[i].y);        }        context.strokeStyle = this.color;        context.stroke();    }    update() {        this.timer--;        if (this.timer >= 1) {            let x = Math.floor(this.x / this.effect.cellSize);            let y = Math.floor(this.y / this.effect.cellSize);            let index = y * this.effect.cols   x;            let angle = this.effect.flowField[index];            this.speedX = Math.cos(angle);            this.speedY = Math.sin(angle);            this.x  = this.speedX * this.speedModifier;            this.y  = this.speedY * this.speedModifier;            this.history.push({ x: this.x, y: this.y });            if (this.history.length > this.maxLength) {                this.history.shift();            }        } else if (this.history.length > 1) {            this.history.shift();        } else {            this.reset();        }    }    reset() {        this.x = Math.floor(Math.random() * this.effect.width);        this.y = Math.floor(Math.random() * this.effect.height);        this.history = [{ x: this.x, y: this.y }];        this.timer = this.maxLength * 2;    }}

Explicação:


4. Classe de Efeitos: Organizando a Animação

A classe Effect cuida da criação de partículas e do próprio campo de fluxo, que controla o movimento das partículas.

class Effect {    constructor(canvas) {        this.canvas = canvas;        this.width = this.canvas.width;        this.height = this.canvas.height;        this.particles = [];        this.numberOfParticles = 3000;        this.cellSize = 20;        this.flowField = [];        this.curve = 5;        this.zoom = 0.12;        this.debug = true;        this.init();    }    init() {        this.rows = Math.floor(this.height / this.cellSize);        this.cols = Math.floor(this.width / this.cellSize);        for (let y = 0; y < this.rows; y  ) {            for (let x = 0; x < this.cols; x  ) {                let angle = (Math.cos(x * this.zoom)   Math.sin(y * this.zoom)) * this.curve;                this.flowField.push(angle);            }        }        for (let i = 0; i < this.numberOfParticles; i  ) {            this.particles.push(new Particle(this));        }    }    drawGrid(context) {        context.save();        context.strokeStyle = \\'white\\';        context.lineWidth = 0.3;        for (let c = 0; c < this.cols; c  ) {            context.beginPath();            context.moveTo(c * this.cellSize, 0);            context.lineTo(c * this.cellSize, this.height);            context.stroke();        }        for (let r = 0; r < this.rows; r  ) {            context.beginPath();            context.moveTo(0, r * this.cellSize);            context.lineTo(this.width, r * this.cellSize);            context.stroke();        }        context.restore();    }    render(context) {        if (this.debug) this.drawGrid(context);        this.particles.forEach(particle => {            particle.draw(context);            particle.update();        });    }}

Explicação:


5. Dando vida ao loop de animação

Para fazer tudo funcionar, precisamos de um loop de animação que limpe continuamente a tela e renderize novamente as partículas:

const effect = new Effect(canvas);function animate() {    ctx.clearRect(0, 0, canvas.width, canvas.height);    effect.render(ctx);    requestAnimationFrame(animate);}animate();

Explicação:


Conclusão

Ao dividir as classes Particle e Effect, criamos uma animação de campo de fluxo fluida e dinâmica usando apenas JavaScript vanilla. A simplicidade da tela HTML, combinada com as funções trigonométricas do JavaScript, nos permite construir esses efeitos visuais fascinantes.

Sinta-se à vontade para brincar com a contagem de partículas, as cores ou a fórmula do campo de fluxo para criar seus próprios efeitos exclusivos!

","image":"http://www.luping.net/uploads/20241022/17296041676717aa472ee02.jpg","datePublished":"2024-11-09T01:12:23+08:00","dateModified":"2024-11-09T01:12:23+08:00","author":{"@type":"Person","name":"luping.net","url":"https://www.luping.net/articlelist/0_1.html"}}
"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Tela de campo de fluxo

Tela de campo de fluxo

Publicado em 2024-11-09
Navegar:598

Flow Field Screen

Campos de fluxo dinâmico com Vanilla JS e HTML Canvas

Você já ficou hipnotizado por animações abstratas de partículas? Esses visuais fluidos e dinâmicos podem ser obtidos com técnicas surpreendentemente simples, usando JavaScript simples e o elemento HTML canvas. Neste artigo, detalharemos o processo de criação de um campo de fluxo que anima milhares de partículas, dando-lhes um movimento natural.

1. Configurando o Projeto

Para começar, precisamos de três arquivos: um arquivo HTML para configurar a tela, um arquivo CSS para estilizar e um arquivo JavaScript para lidar com a lógica.



    Flow Fields

Explicação:

  • Definimos um elemento onde todas as nossas animações acontecerão.
  • O estilos.css será vinculado ao estilo da tela.
  • A principal lógica de animação está contida em script.js.

2. Estilizando o Canvas com CSS

Vamos adicionar um estilo simples para dar à nossa tela um fundo preto e garantir que todo o preenchimento e margens sejam removidos.

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

canvas {
    background-color: black;
}

Explicação:

  • Definir margem e preenchimento como zero garante que a tela preencha toda a tela.
  • O fundo preto fornece um bom contraste para as partículas brancas.

3. Classe de Partículas: Criando a Magia

A classe Particle é onde está o núcleo da animação. Cada partícula se move pela tela, deixando um rastro de suas localizações anteriores, criando o efeito de fluxo.

class Particle {
    constructor(effect) {
        this.effect = effect;
        this.x = Math.floor(Math.random() * this.effect.width);
        this.y = Math.floor(Math.random() * this.effect.height);
        this.speedModifier = Math.floor(Math.random() * 5   1);
        this.history = [{ x: this.x, y: this.y }];
        this.maxLength = Math.floor(Math.random() * 200   10);
        this.timer = this.maxLength * 2;
        this.colors = ['#4C026B', '#8E0E00', '#9D0208', '#BA1A1A', '#730D9E'];
        this.color = this.colors[Math.floor(Math.random() * this.colors.length)];
    }

    draw(context) {
        context.beginPath();
        context.moveTo(this.history[0].x, this.history[0].y);
        for (let i = 1; i = 1) {
            let x = Math.floor(this.x / this.effect.cellSize);
            let y = Math.floor(this.y / this.effect.cellSize);
            let index = y * this.effect.cols   x;
            let angle = this.effect.flowField[index];

            this.speedX = Math.cos(angle);
            this.speedY = Math.sin(angle);
            this.x  = this.speedX * this.speedModifier;
            this.y  = this.speedY * this.speedModifier;

            this.history.push({ x: this.x, y: this.y });
            if (this.history.length > this.maxLength) {
                this.history.shift();
            }
        } else if (this.history.length > 1) {
            this.history.shift();
        } else {
            this.reset();
        }
    }

    reset() {
        this.x = Math.floor(Math.random() * this.effect.width);
        this.y = Math.floor(Math.random() * this.effect.height);
        this.history = [{ x: this.x, y: this.y }];
        this.timer = this.maxLength * 2;
    }
}

Explicação:

  • Construtor: Cada partícula é inicializada com uma posição e velocidade de movimento aleatórias. A matriz de histórico rastreia posições anteriores para criar trilhas.
  • draw(): Esta função desenha o caminho da partícula com base em seu histórico. A partícula deixa um rastro colorido que aumenta o efeito visual.
  • update(): Aqui, a posição da partícula é atualizada calculando o ângulo do campo de fluxo. A velocidade e a direção são controladas por funções trigonométricas.
  • reset(): Quando a partícula termina sua trilha, ela é redefinida para um novo local aleatório.

4. Classe de Efeitos: Organizando a Animação

A classe Effect cuida da criação de partículas e do próprio campo de fluxo, que controla o movimento das partículas.

class Effect {
    constructor(canvas) {
        this.canvas = canvas;
        this.width = this.canvas.width;
        this.height = this.canvas.height;
        this.particles = [];
        this.numberOfParticles = 3000;
        this.cellSize = 20;
        this.flowField = [];
        this.curve = 5;
        this.zoom = 0.12;
        this.debug = true;
        this.init();
    }

    init() {
        this.rows = Math.floor(this.height / this.cellSize);
        this.cols = Math.floor(this.width / this.cellSize);
        for (let y = 0; y  {
            particle.draw(context);
            particle.update();
        });
    }
}

Explicação:

  • Construtor: inicializa as dimensões da tela, o número de partículas e o campo de fluxo.
  • init(): Calcula os ângulos para o campo de fluxo combinando funções trigonométricas para cada célula da grade. Este campo influencia como as partículas se movem.
  • drawGrid(): Desenha a grade que divide a tela em células, usada na depuração.
  • render(): chama os métodos draw e update para cada partícula para animar as partículas na tela.

5. Dando vida ao loop de animação

Para fazer tudo funcionar, precisamos de um loop de animação que limpe continuamente a tela e renderize novamente as partículas:

const effect = new Effect(canvas);

function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    effect.render(ctx);
    requestAnimationFrame(animate);
}
animate();

Explicação:

  • clearRect(): Limpa a tela em cada quadro para evitar desenhar sobre os quadros anteriores.
  • requestAnimationFrame: mantém a animação suave chamando recursivamente a função animate().

Conclusão

Ao dividir as classes Particle e Effect, criamos uma animação de campo de fluxo fluida e dinâmica usando apenas JavaScript vanilla. A simplicidade da tela HTML, combinada com as funções trigonométricas do JavaScript, nos permite construir esses efeitos visuais fascinantes.

Sinta-se à vontade para brincar com a contagem de partículas, as cores ou a fórmula do campo de fluxo para criar seus próprios efeitos exclusivos!

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/ibra-kdbra/flow-field-screen-567c?1 Se houver alguma violação, entre em contato com [email protected] para excluí-lo
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3