Mergulho profundo de codificação criativa para iniciantes | Frank Dvorak | Skillshare

Velocidade de reprodução


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Mergulho profundo de codificação criativa para iniciantes

teacher avatar Frank Dvorak, Creative Coding

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Aulas neste curso

    • 1.

      Apresentação

      0:39

    • 2.

      Configuração de HTML e CSS

      1:20

    • 3.

      Configuração de JavaScript

      2:08

    • 4.

      Como desenhar retângulos

      1:30

    • 5.

      Como desenhar linhas

      3:10

    • 6.

      Programação orientada a objetos

      5:24

    • 7.

      Cores dinâmicas com HSL

      1:52

    • 8.

      Arte de linha randomizada

      3:26

    • 9.

      Desenhando linhas multi-segmented

      3:25

    • 10.

      Linhas de animação

      4:36

    • 11.

      Efeito de tempestade de Rainbow

      5:29

    • 12.

      Degradês lineares

      2:24

    • 13.

      Degradês radiais

      1:14

    • 14.

      Como preencher formas com um padrão

      4:03

    • 15.

      Melhore seus efeitos com sombras

      1:42

    • 16.

      Trigonometria

      1:51

    • 17.

      Efeito de rabiscos de caos

      4:43

    • 18.

      O que é um campo de fluxo

      1:07

    • 19.

      Configuração de tela HTML

      1:28

    • 20.

      Desenhando formas em tela

      2:52

    • 21.

      Programação orientada a objetos no JavaScript

      8:07

    • 22.

      Desenho de sistemas de partículas

      1:17

    • 23.

      Animando sistemas de partículas

      3:54

    • 24.

      Desenhando linhas e trilhas

      3:46

    • 25.

      Padrões de movimento com trigonometria

      1:16

    • 26.

      Criando um campo de vetor

      8:03

    • 27.

      Como criar um campo de fluxo

      7:04

    • 28.

      Experimentos de campo de fluxo

      3:28

    • 29.

      Modo de grade e depuração

      8:17

    • 30.

      Cores randomizadas

      2:54

    • 31.

      Design responsivo

      5:15

    • 32.

      Experimentando com padrões de campo de fluxo

      2:43

    • 33.

      Desenho de texto

      5:53

    • 34.

      Entendendo os dados dos pixels

      5:13

    • 35.

      Tratando dados de pixels

      3:42

    • 36.

      Convertendo cores em ângulos

      10:28

    • 37.

      Fluxo e gradientes

      4:47

    • 38.

      Dicas, truques e experimentos

      10:39

    • 39.

      Campos de fluxo de imagem explicados

      8:27

    • 40.

      Truques de manipulação de cores

      10:22

  • --
  • Nível iniciante
  • Nível intermediário
  • Nível avançado
  • Todos os níveis

Gerado pela comunidade

O nível é determinado pela opinião da maioria dos estudantes que avaliaram este curso. Mostramos a recomendação do professor até que sejam coletadas as respostas de pelo menos 5 estudantes.

177

Estudantes

1

Projeto

Sobre este curso

Fazer coisas bonitas com código pode ser fácil se você der isso passo a passo. Vamos explorar a codificação criativa e descobrir o que pode ser feito combinando diferentes técnicas de desenho e animação.

O conhecimento é poder. É por isso que vamos usar apenas princípios de programação básicos — funções, arrays e principles—functions, JavaScript de baunilha simples, sem estruturas e nenhuma bibliotecas. Vou explicar todas as linhas de código enquanto criamos vários projetos animados. Ser capaz de entender plenamente como o código funciona nos permitirá obter controle completo sobre o código, e podemos fazer isso fazer tudo o que quisermos.

Deixe-me mostrar-lhe como desenhar uma linha simples, animá-la e, em seguida, transformá-la em efeitos cada vez mais complexos enquanto adicionamos mais técnicas ao nosso kit de ferramentas de codificação criativo, uma a uma.

Descubra os segredos da codificação criativa hoje. O maior segredo é que é realmente muito mais fácil do que você acha que criar animações complexas e bonitas. Você só tem que dar isso passo a passo. Tudo faz sentido se você quebrar o processo em partes individuais.

Aulas 1 - 16:

No primeiro bloco amigável para iniciantes, vamos aprender como desenhar formas na tela e como animá-las, transformando-as em espirais animadas, parafusos de raios arco-íris e rabiscos aleatórios.

Aulas 17 - 39:

Se você já entender os conceitos básicos de desenhar em uma tela HTML, você pode pular diretamente para a Seção 2, onde eu inicio o projeto de curso principal do zero. Criaremos um campo de fluxo animado, experimentaremos com ele e tornaremos ele dobrar em torno de texto e imagens.

Divirta-se!

Conheça seu professor

Teacher Profile Image

Frank Dvorak

Creative Coding

Professor

Hello, I'm Frank. I'm a front-end web developer, owner of Frank's Laboratory YouTube channel. Come explore creative coding, game development and generative art with me.

Visualizar o perfil completo

Habilidades relacionadas

Animação e 3D Movimento e animação
Level: Beginner

Nota do curso

As expectativas foram atingidas?
    Superou!
  • 0%
  • Sim
  • 0%
  • Um pouco
  • 0%
  • Não
  • 0%

Por que fazer parte da Skillshare?

Faça cursos premiados Skillshare Original

Cada curso possui aulas curtas e projetos práticos

Sua assinatura apoia os professores da Skillshare

Aprenda em qualquer lugar

Faça cursos em qualquer lugar com o aplicativo da Skillshare. Assista no avião, no metrô ou em qualquer lugar que funcione melhor para você, por streaming ou download.

Transcrições

1. Apresentação: Coisas boas e bonitas com código podem ser fáceis se você as seguir passo a passo, tudo faz sentido se você dividi-lo em partes individuais Deixe-me mostrar como usar princípios básicos de programação, funções, matrizes e loops para criar bases complexas de código animado. Depois de entendermos completamente as técnicas, passaremos para o próximo nível na seção avançada. Hoje, vamos descobrir as ferramentas, fazer experiências com código e usar esse conhecimento para criar nossas próprias animações. Vamos fazer arte com código e aprender programação ao mesmo tempo. Divirta-se. 2. Configuração de HTML e CSS: Nesta primeira seção, criarei um projeto separado para iniciantes. Aprenderemos como animar linhas e como transformá-las em vários efeitos diferentes, como raios, espirais, ondas e assim por diante. Se quiser, você pode ir direto para a seção do campo de fluxo, que começa com menos de 17. Incluí downloads de código-fonte durante os pontos-chave de cada projeto. Assim, é mais fácil alternar entre os projetos e experimentar o código. Se é isso que você quer fazer, eu o guiarei por todo o processo passo a passo e explicarei cada linha de código, mas é necessário algum conhecimento básico de HTML, CSS e JavaScript para obter o valor máximo. Aqui, estou apenas configurando uma página web genérica básica com o elemento de tela HTML nela. Eu vinculei aos arquivos style.css e script.js. E então eu declaro alguns estilos CSS para tela e crio regras de redefinição globais para garantir que as margens e os preenchimentos pareçam iguais em diferentes navegadores. Eu recomendo usar um navegador moderno para essa classe, idealmente o Google Chrome. Você pode ver que estou usando essa posição absoluta comum, centro e técnica para garantir que o Canvas esteja no meio da página da web, vertical e horizontalmente. 3. Configuração de JavaScript: Configuração básica dentro do index.HTML e do estilo CSS, passamos para script.js. Toda a nossa lógica será escrita aqui. Eu configurei meu elemento de tela HTML, nossa prancheta de desenho com as duas linhas de código usuais. Eu criei uma variável personalizada que chamo, por exemplo , canvas, e apontei para o elemento canvas que criamos em index.HTML usando seu ID. Eu dei a ele uma identificação do Canvas One. Então eu crio uma variável de contexto, CTX. Eu pego aquela variável de tela que acabei de criar e chamo o método getContext embutido nela. Esse método cria o chamado desenho em contexto, que é basicamente um objeto JavaScript com todos os métodos e propriedades de desenho do Canvas integrados. Passamos a ele um argumento chamado tipo de contextos. Queremos trabalhar com contexto de renderização bidimensional. Hoje, o elemento de tela tem dois tamanhos independentes. Tamanho do elemento, tamanho real do elemento HTML e tamanho da superfície do desenho. Queríamos garantir que esses dois tamanhos fossem definidos com os mesmos valores. Eu faço isso não definindo o tamanho da tela em CSS e apenas certos atributos de largura e altura no Canvas para os valores. Eu quero assim. Se você também estiver declarando o tamanho da tela em seu arquivo CSS, certifique-se de que ela esteja definida com os mesmos valores para evitar desenhos esticados ou distorcidos. Se eu consolar log c dx da linha dois, podemos ver esse objeto de contexto de renderização de tela sobre o qual falei. Dentro. Podemos ver as configurações padrão do Canvas, como a fonte atual do estilo de preenchimento. Podemos ver que o estilo de traçado padrão está definido como preto aqui, por exemplo, também podemos ver todos os métodos de desenho integrados do Canvas. Hoje, vamos nos concentrar em desenhar e animar linhas. Então, aprenderemos tudo o que você precisa saber sobre o método start path que vem daqui. Também temos o método do caminho fechado aqui, a linha até aqui e a mudança para o método aqui. Vamos usar esses métodos para entender completamente o que eles fazem e como funcionam. 4. Como desenhar retângulos: Podemos desenhar muitas formas diferentes no Canvas, formas muito básicas são círculos e retângulos. Desenhar um retângulo é muito simples. Podemos pegar contextos que definimos na linha dois. Sabemos que ele contém uma referência ao objeto que contém todos os métodos de desenho em tela. A partir daí, chamamos o método de preenchimento de retângulo embutido. retângulo de preenchimento espera coordenadas a partir das quais começaremos a desenhar no retângulo, o canto superior esquerdo do retângulo. Coordenada X, a distância do canto superior esquerdo do retângulo da borda esquerda da tela será de 100 pixels, coordenada y, a distância da parte superior também será de 100 pixels. A largura do retângulo será 50 pixels e a altura de 150. Posso alterar a largura para 200 pixels, coordenada y vertical 250 pixels. Acho que você entendeu por padrão, o preenchimento das formas desenhadas no Canvas está definido como preto. Posso usar a propriedade fillStyle para substituir o valor padrão e posso configurá-lo para outra coisa. Vamos experimentar o vermelho. Também podemos chamar o método de retângulo de traçado embutido, que apenas delineará a forma. Por padrão, será uma linha preta com uma largura de pixel. Eu posso mudar isso usando a propriedade de largura da linha. Vamos testar dez pixels. E eu posso usar um estilo de traçado para mudar a cor de todas as linhas desenhadas no Canvas, por exemplo, azul. 5. Como desenhar linhas: Então, esses são os princípios básicos do desenho de formas no Canvas. Hoje, vamos nos concentrar em desenhar linhas. Eles funcionam um pouco diferente dos retângulos. Precisamos começar pelo método de caminho inicial embutido com dois pontos. Esse método iniciará um novo caminho e também fechará automaticamente todos os caminhos existentes, se houver algum. Isso é importante porque, dessa forma, você pode desenhar cada linha em uma cor diferente e, sem iniciar o caminho, todas as suas linhas se unirão automaticamente em uma forma massiva, que não é o que queremos hoje. Certo? Agora, só queremos desenhar uma linha simples. Começamos usando o método move to integrado. Esse método criará um novo subcaminho para nossos propósitos e propósitos. Vamos pensar em mudar para métodos como uma forma de definir as coordenadas iniciais x e y da nossa linha. Em seguida, usaremos métodos line to que criarão uma linha reta a partir do subcaminho, do ponto definido em move para dois, as coordenadas que passamos para a linha dois. Por enquanto, vamos pensar que os métodos da linha dois representarão as coordenadas x e y finais da nossa linha. Vá para a linha final, dois métodos apenas definem o caminho. Eles não renderizam nada diretamente para desenhar o caminho até nós, temos que usar o método de traçado embutido. Agora, estamos desenhando uma linha a partir das coordenadas 300, 302, coordenadas 350, 400. Podemos alterar esses valores para mudar onde nossa linha começa e onde termina. Eu posso deletar o retângulo. Agora, nessa área, eu queria definir configurações globais. A largura da linha será de dez pixels ou 100. Eu movo as coordenadas. Temos muitas outras propriedades que podemos usar aqui. Você pode ver todos eles se o console registrar CTX da linha dois, como fizemos antes, por exemplo, veja o que acontece quando eu disse a propriedade Line Cap para arredondar. Eu defini o estilo do traçado como magenta, a largura da linha como dez. Também podemos agrupar vários métodos de duas linhas como este. cada nova linha, dois métodos, definiremos outro ponto na forma que será conectado ao nosso subcaminho. E o dentista escreveu: esse é o principal conceito de animação que estamos fazendo hoje. Teremos uma linha que começa em algum lugar. Em seguida, teremos muitas chamadas da linha dois para encontrar pontos ao longo desse caminho. E semelhante ao clássico jogo de cobra, vamos animar isso sempre adicionando um novo segmento de linha ao início e removendo o último segmento, fazendo parecer que a linha está rastejando pela tela. Eu adiciono uma nova linha. Eu adiciono mais um. Eu removo o segmento mais antigo, adiciono outra nova linha. Vamos automatizar isso e brincar com as coordenadas que passamos para essas linhas para criar interesse nos padrões de movimento. Depois de entender esse conceito, nós o usaremos para criar belos campos de fluxo como este em uma classe avançada. Pode ser mais fácil do que você pensa fazer as linhas fluírem em torno de imagens ou letras. 6. Programação orientada a objetos: Agora que entendemos o conceito, vamos ampliá-lo. Eu queria criar uma classe JavaScript personalizada que desenhasse e animasse linhas para mim Eu queria animar várias linhas ao mesmo tempo. Portanto, usar uma aula é ideal aqui. construtor de classes é um método especial para criar uma instância de uma classe. Quando o chamamos com a nova palavra-chave later class constructor, criaremos um novo objeto JavaScript em branco e ele definirá suas propriedades e valores com base no esquema interno. Então, vamos definir esse modelo. Quero que você comece de forma muito simples e depois otimizaremos o código para garantir que esteja absolutamente claro o que está acontecendo. Cada objeto de linha terá coordenadas iniciais x e y. Portanto, uma propriedade personalizada que eu chamo, por exemplo start x será um ponto aleatório entre zero e largura horizontalmente. coordenada vertical inicial de cada linha será um valor aleatório entre zero e meio que a altura vertical. Então, quando combinamos essas coordenadas aleatórias x e y, isso nos dará um ponto em algum lugar dentro da área da tela. Eu quero fazer a mesma coisa para terminar as coordenadas x e y desta forma. Assim, quando um novo objeto de linha é criado, ele é atribuído aleatoriamente aos pontos inicial e final. Vamos usar um método de desenho personalizado para desenhar uma linha entre esses dois pontos. Eu chamo começar o caminho primeiro. Vá para o método para definir as coordenadas iniciais x e y da linha. Método da linha dois para definir as coordenadas x e y finais da linha. E chamamos stroke para realmente renderizar esse caminho no Canvas. Temos uma aula, nosso plano está pronto. Como podemos realmente usá-lo para criar um objeto de linha? Eu crio uma variável constante, chamo a linha um. Eu o defini como igual a uma nova linha como esta. A nova palavra-chave procurará uma classe com esse nome e acionará seu construtor de classe. Construtor de classe, criaremos um novo objeto JavaScript em branco e ele atribuirá valores e propriedades com base no modelo dentro desse objeto que serão salvos em nojo da variável da linha um. Como esse objeto foi criado usando a classe de linha, ele tem acesso a esse método de desenho público e posso chamá-lo assim: desenho de linha com um ponto, coordenadas aleatórias de início e término foram calculadas e uma linha foi desenhada perfeitamente. Na linha sete, largura de linha incerta de até dez pixels. Mas talvez eu queira que cada linha criada pela classe tenha uma largura aleatória dentro de um intervalo predefinido. Eu criei essa propriedade de largura da linha de pontos e ela será um valor aleatório, de 1 a 16 pixels. Vou embrulhá-lo em Math.floor para que não obtenhamos valores de subpixel. É um bom hábito fazer isso com tudo o que desenhamos no Canvas sempre que possível. Eu também poderia ter feito isso para as coordenadas x e y. Eu pego CTX da largura da linha para a linha e o defino com esse valor aleatório da largura da linha. Agora, toda vez que eu atualizo a janela do meu navegador, alinhamento com a posição aleatória e a largura da linha aleatória será desenhada. Estamos fazendo algo que é considerado uma prática ruim aqui. Eu defini a variável canvas na linha um e estou usando essa mesma variável diretamente dentro da minha classe. Eu faço o mesmo com a variável ctx. O código funcionará, mas se você estiver escrevendo código orientado a objetos, o objetivo é manter suas classes independentes de seu ambiente léxico, independente do código que está fora da própria classe. Certo? Agora, essa classe só funcionará se as variáveis Canvas e CTX estiverem definidas aqui. A maneira correta de fazer isso é converter essas variáveis externas em propriedades de classe. Dessa forma, ela será passada para o construtor da classe aqui quando a classe for criada. E eles podem vir de qualquer lugar em nossa base de código, tornando nossa classe mais independente e reutilizável. Você costuma me perguntar por que eu faço isso nos comentários, então espero que isso explique isso. construtor da classe Line espera a cannabis como argumento. Dentro. Eu converto esse argumento em uma propriedade de classe. Estou dizendo que pegue a variável canvas que foi passada aqui e converta-a na propriedade Canvas nesta instância da classe de linha que você está criando agora. Então, podemos usar esse ponto Canvas da linha 12 aqui, em vez de puxar diretamente a variável da linha um. Para fazer tudo isso funcionar, eu sei que o construtor da classe de linha nos espera como argumento. Então, eu pego a variável canvas da linha um e a passo como argumento aqui. Quando criamos uma instância dessa classe com a nova palavra-chave perfect, também estamos retirando diretamente a variável CTX da terra para nossa classe aqui. Portanto, nosso método de sorteio público espera contexto como argumento e será usado aqui. Em seguida, pegamos a variável CT x da linha dois e a passamos para o método de desenho aqui embaixo. Quando o chamamos assim, o CTX será convertido em contexto aqui. Então, é assim que você torna as aulas mais independentes e menos dependentes do frio ambiente fora daquela aula. 7. Cores dinâmicas com HSL: Estamos definindo o estilo de traçado na linha oito, mas talvez eu queira que a cor das linhas também seja aleatória. Nesse caso, tenho que definir o estilo do traçado dentro do método de desenho aqui. Eu disse que é para escrevê-lo só para testá-lo. Se estiver funcionando. Eu queria atribuir uma cor aleatória toda vez que criamos uma nova linha. A maneira mais fácil de fazer isso é usando a declaração de cores HSL na web Podemos definir cores de várias maneiras diferentes. Você tem suas declarações de cores RGB e hexadecimais padrão com as quais todos estão familiarizados. Também podemos usar declaração de cor HSL, matiz, saturação e luminosidade. O primeiro argumento aqui, você representará um grau na roda de cores 0-360. A saturação será de 100 por cento. Queremos cores completas. A luminosidade será de 50 por cento. Queremos uma cor que não seja afetada pela luz ou pelo escuro. Zero grau na roda de cores está certo, como você pode ver, 120 é verde, 240 é azul, 360. Nós pedalamos de volta ao vermelho. De novo. À medida que aumentamos a visualização, percorremos todas as cores intermediárias. Se formos mais do que 360, nós apenas pedalamos desde o início da cor vermelha novamente. A declaração de cores Hsl é estruturada de forma a facilitar a randomização das cores ou o ciclo dinâmico pelo espectro de cores. Eu crio uma propriedade de classe personalizada. Eu chamo isso de visão de pontos. Será um valor aleatório de 0 a 360, e eu quero apenas números inteiros. Então, Math.floor, tornaremos o estilo de traçado dinâmico substituindo o valor de matiz codificado essa variável aleatória como esta. E é isso. Toda vez que eu atualizo a página, calculamos aleatoriamente uma cor diferente. 8. Arte de linha randomizada: Como dissemos, a classe JavaScript é um modelo. Podemos usá-lo para criar muitos objetos semelhantes. Então, por que estamos criando apenas uma linha aleatória? Vamos criar muito mais. Neste momento, é muito fácil. Primeiro eu crio uma variável chamada matriz de leões. Essa será uma matriz para armazenar todos os objetos aéreos em um só lugar. Agora eu posso criar um for-loop. Isso for loop será executado, por exemplo, dez vezes. Toda vez que ele é executado, eu pego a matriz de linhas e chamo o método embutido de push de matriz. Método push. Vamos usar tudo o que passarmos para ele como argumento e ele o empurrará até o final da matriz. Vou passar uma nova linha. E online 11, posso ver que o construtor da classe de linha espera o Canvas como argumento. Então eu passo a variável canvas da linha um. Eu excluo esse código e consola a matriz de linhas de log. Como esperado, ele contém dez objetos de linha criados usando nossa classe de linha personalizada. Eu abro um e inspecionei para ter certeza de que todas as propriedades têm valores. Quero que você verifique se nada está indefinido, o que seria um sinal de um problema. Tudo está bem aqui. Também posso criar várias linhas, uma variável, e configurá-la como 50. Eu o uso aqui no for-loop. No console, posso ver que a matriz de linhas agora contém 50 objetos de linha com posições aleatórias, largura de linha e cores. Como os desenhamos? Como estamos mantendo todos os objetos de alinhamento dentro da matriz de linhas, podemos simplesmente chamar a matriz embutida para cada método nela, pois cada método chamará uma função de retorno de chamada fornecida uma vez para cada elemento da matriz. Então, internamente, para cada objeto de linha na matriz, quero chamar seu método de desenho associado que definimos na linha 20. Se você está se perguntando de onde vem essa palavra objeto, é apenas uma palavra aleatória que eu escolhi usar. Basicamente, somos um login em cada objeto na matriz, um nome de variável que será usado para se referir a esse objeto dentro de cada método, esse nome de variável pode ser qualquer coisa, desde que continuemos nos referindo a ela dessa forma em qualquer lugar dentro desse método de retorno de chamada, também posso chamá-lo de linha, por exemplo para cada objeto de linha dentro da matriz de linhas chamado método draw. Na linha 20, posso ver que o método de desenho espera contexto como argumento. Então eu passo a variável CTX. Definimos na linha dois. Estamos desenhando 50 linhas em tela. Cada um tem coordenadas iniciais e finais aleatórias, largura e cor aleatórias. Você pode atualizar a página para gerar um novo conjunto de valores aleatórios e desenhá-los no Canvas. Parabéns se este for seu primeiro projeto de codificação criativa, essa é uma forma muito simples de arte gerada processualmente, a chamada arte generativa. arte generativa é uma colaboração entre um humano e uma máquina. As regras e o escopo desta obra de arte são decididos por nós, humanos. Mas algumas das características, neste caso cores e posições, são decididas aleatoriamente por um computador. É claro que existem formas muito mais avançadas de arte generativa. E fiz muitas aulas em que exploramos isso de maneiras diferentes. Vamos ver onde podemos levar esse. Vamos animá-lo. 9. Desenhando linhas multi-segmented: Para maior clareza, voltarei a uma linha para que possamos ver melhor o que está acontecendo. Como dissemos no início, eu queria ter uma linha feita de vários segmentos. Adicionaremos novos segmentos e removeremos os antigos para fazer com que pareça que estão circulando como o clássico jogo de cobras. Preciso fazer algumas mudanças na classe de linha para conseguir isso, precisaremos de apenas um conjunto de coordenadas x e y, assim. Essas coordenadas serão atualizadas a cada tique-taque do loop de animação e adicionaremos e manteremos um certo número de posições em uma matriz de histórico que eu defino aqui. Primeiro, será um objeto simples com propriedades x e y iguais a esse ponto x e esse ponto y. Acabamos de randomizar aqui. Esse histórico de nós é um objeto agora, mas será uma matriz em que cada elemento nessa matriz é um objeto como esse com coordenadas x e y. Move to method definirá as coordenadas x e y iniciais do nosso caminho. E será esse índice zero de matriz de histórico de pontos, que será um objeto como este. E acessamos sua coordenada x e também sua coordenada y. Digamos que eu manterá dez objetos dentro da matriz histórica. Cada um tem seu valor de posição x e y. Aqui, quero percorrer quantas posições ocupamos na matriz histórica e quero conectá-las a uma linha. Então, eu crio um loop for que será executado quantas vezes dependendo do comprimento dessa matriz de histórico de pontos da linha 15. E cada vez que for executado, ele pegará um objeto, que ficará assim naquele índice na matriz, e passará suas coordenadas x e y para o método da linha dois. Então, passamos para o método para definir a posição inicial x e y da linha. E então percorremos todas as outras posições e as conectamos com uma linha. Em seguida, chamamos stroke para renderizar esse caminho multisegmentado no Canvas. Ainda não temos um loop de animação, então criarei outro loop for que simplesmente executaremos três vezes e criaremos três posições aleatórias x e y. Preciso ter certeza de que a história da pedra aqui em cima é na verdade uma matriz. Inicialmente, ele conterá apenas um elemento com índice zero. Será esse objeto que terá propriedades x e y definidas com as coordenadas desse ponto x e y. Aqui eu corro um for-loop três vezes. Cada vez que ele é executado, eu crio novas posições aleatórias x e y. Eu pego a matriz do histórico de distorções e coloco outro objeto com essas novas propriedades x e y em seu cuidado com os colchetes aqui. Bom. Toda vez que eu atualizo a janela do navegador, desenhamos uma nova linha de vários segmentos iniciando as coordenadas x e y. E para um loop que é executado 123 vezes cada vez criando um segmento de linha, um subcaminho. Posso fazer o for-loop funcionar 30 vezes se eu quiser, o que criará uma forma muito mais complexa. Espero que esteja claro agora como o conceito de matriz histórica funciona. Agora vamos dar um passo adiante para animá-lo. 10. Linhas de animação: Eu crio uma função personalizada que chamo, por exemplo, animate. Dentro, traçaremos uma linha. Vamos atualizá-lo. E então chamamos o Request Animation Frame embutido, que informa ao navegador que queremos executar uma animação. Isso fará com que o navegador chame uma função que especificamos antes da próxima repintura. Na prática, isso significa que eu simplesmente passo o nome de sua função principal, animo executa, ele faz alguma coisa e, em seguida, solicito o quadro de animação. Chamaremos de animate novamente, criando um loop de animação repetitivo sem fim. método de quadro de animação de solicitação se encaixa no objeto da janela, mas pode ser chamado diretamente dessa forma. Então, aqui nós definimos animar. Preciso ligar para ele. Para iniciar o primeiro loop de animação. Eu coloquei um registro do console que diz animação, apenas para verificar se o loop está realmente em execução. Sim, eu apaguei. Quero colocar nosso código de sorteio assim. Isso está apenas criando um crescimento infinito na fila. Podemos comentar temporariamente o esboço dos sete. Se o seu computador tiver problemas com isso, nós o corrigiremos em um segundo. Quero excluir a pintura antiga entre todos os quadros de animação, então chamo o método de retângulo transparente embutido. Quero limpar toda a tela da coordenada zero até a largura e a altura da tela. Ok, eu comento isso porque estamos adicionando 30 segmentos de linha repetidamente matriz histórica aqui na linha 20 para criar uma matriz de crescimento infinito, eu crio um método de atualização na classe de linha para cada quadro de animação, toda vez que o método de atualização é executado, quero adicionar um novo segmento à nossa linha. Vou deletar tudo isso. Eu descomento a linha 47. E para cada marca de animação, quero que você chame o método de desenho em cada objeto dentro da matriz de linhas. Atualmente, temos apenas um objeto lá dentro. Eu também queria chamar o método de atualização que acabamos de definir. Agora podemos ver a linha sendo desenhada segmento por segmento. Não faz sentido percorrer a mesma matriz duas vezes aqui. Então, em vez disso, chamo draw e update na mesma função de callback. Cuidado com os colchetes aqui. É para cometer um erro e cometer um erro? Bom. Não quero que esteja desenhando um caminho com uma quantidade infinitamente crescente de pontos. Eu quero ter um certo comprimento máximo. E quando isso for alcançado, removeremos o segmento mais antigo e adicionaremos um novo. Digamos que eu queira que o caminho tenha dez segmentos. Método de atualização interno. Ao adicionar um novo segmento, verifico se o comprimento da matriz do histórico é maior do que o comprimento máximo. Se for mais de dez, usaremos o método embutido de mudança de matriz. método de deslocamento de matriz remove o primeiro elemento da matriz porque estamos usando o método push para adicionar um novo segmento. O método push adiciona um novo elemento ao final da matriz. método Shift removerá o segmento mais antigo para nós desde o início da matriz. E aqui chegamos ao segundo passo em nossa linha processual artística. O que você acha disso? Ele escala, mas com regras, podemos adicionar quantas linhas quisermos. Todos eles têm largura e cor aleatórias devido à lógica que escrevemos no início estamos apenas escolhendo aleatoriamente pontos dentro da cannabis. E se quisermos alguma sensação de movimento contínuo? Queremos que a posição atualizada do próximo segmento tenha alguma relação com a posição do segmento anterior. Isso está nos deixando um passo mais perto de um campo de fluxo real. Espero que você esteja obtendo algum valor. Vamos explorar o movimento e agora vou pensar em nossa linha como uma partícula. Seu primeiro segmento está se movendo ao longo da tela em uma determinada velocidade e direção. Os outros segmentos seguem. Eu dou a cada linha velocidade X, velocidade horizontal e velocidade. Por que velocidade vertical? Começaremos de um ponto aleatório em algum lugar dentro da área da tela. E toda vez que chamamos o método de atualização, aumentamos a exposição atual pelo valor da velocidade x e a posição vertical y pelo valor da velocidade. Por quê? Loop de animação do Insight Vou descomentar, desenhar e atualizar para ver o que acabamos de fazer. Ok. Eu crio 20 linhas. Sim. Isso é o que está acontecendo. 11. Efeito de tempestade de Rainbow: Estou optando pelo efeito clareador. Eu quero uma tempestade com raios de arco-íris. Toda vez que atualizarmos a posição horizontal pela velocidade x de dez pixels, adicionaremos, além disso, um valor aleatório de 0 a 10 e 50. Que tal um valor aleatório entre -25 e mais 25 na horizontal e os mesmos interesses verticais. Então, quando eu atualizo minha página, recebo um conjunto de relâmpagos muito curtos. Se eu quiser que eles avancem mais de cima para baixo, talvez a velocidade horizontal seja apenas mais u2 e a velocidade vertical 15 ou 46. Eu gostaria que a animação fosse reproduzida e depois reiniciada. Eu poderia, por exemplo, verificar se todos os segmentos saíram da área da tela. Ou eu posso dar a cada linha um cronômetro. Digamos que cada linha tenha uma vida útil máxima da linha 18 vezes dez, cada linha se moverá por 100 quadros de animação. Dentro do método de atualização, aumentarei o cronômetro em um para cada quadro de animação. Como eu faço isso? Se o cronômetro for menor que a vida útil? Nós animamos a linha. Eu também preciso definir esse temporizador de pontos no construtor da classe aqui em cima. E eu inicialmente o configurei para zero. Quando o cronômetro ultrapassa a vida útil, ainda estamos desenhando as linhas, mas não estamos mais adicionando e removendo segmentos, então parece que eles congelaram no espaço. Nesse ponto, quero começar a remover os segmentos um por um até que a linha desapareça. Caso contrário, e aqui vou novamente chamar de mudança na matriz do histórico. Tenha paciência comigo por um segundo. Eu preciso resolver a lógica aqui. Precisamos ter certeza de que sempre haja pelo menos um elemento na matriz. Caso contrário, se o comprimento do ponto do histórico de pontos for menor ou igual a um, chamado método de redefinição. Vamos definir o método de redefinição. Agora, isso vai funcionar? O cronômetro está aumentando enquanto o cronômetro for menor que a vida útil, adicione e remova posições, fazendo com que a linha se arraste. Se o comprimento for menor ou igual a um, redefina-o. Caso contrário, significa que o cronômetro é maior do que a vida útil, mas o comprimento ainda não é menor ou igual a um. Continue removendo um segmento por vez. Acho que isso deveria funcionar. Agora eu preciso definir o método de reinicialização para que possamos apenas colocar a linha de volta em seu estado inicial para que possamos animá-la. De novo. Precisaremos redefinir as posições x e y e adicionaremos essa posição inicial dentro da matriz do histórico. Também redefiniremos o cronômetro para zero para que ele possa contar novamente. Estou recebendo um erro no console. Provavelmente você percebeu isso antes de eu precisar chamar um shift para remover o primeiro segmento da matriz na matriz do histórico real. Assim. Sim, isso é o que eu queria. As linhas se movem em torno de 400 quadros de animação e depois são reiniciadas. Todos eles são reiniciados ao mesmo tempo porque codificamos maxlength para ter o mesmo valor para todos eles. Eu o configurei para um valor aleatório, 10-160 segmentos. Agora estamos tendo uma sensação real de movimento. Também posso randomizar a velocidade x, digamos que um valor aleatório entre -2,5 e mais 2,5 de velocidade, y será seis. Velocidade. Por que dez? Talvez aqui eu deva fazer um valor aleatório entre -0,5 e mais 0,5. Velocidade Y5 sete. Eu também posso jogar com o intervalo aleatório aqui e aqui. Gerar números aleatórios como esse para cada quadro de animação custa muito caro, só para você saber. Mas como não temos milhares de linhas, maioria dos computadores provavelmente nem notará que a redução de quantas vezes sua base de código chama o quadro de animação de pares aleatórios dominado aumentará enormemente o desempenho de seus efeitos. Eu disse expectativa de vida útil máxima vezes três. Você pode ver que temos uma linha que começa em um segmento. Ele cresce até atingir o comprimento máximo e, em seguida, gira até um máximo de três termos. É o comprimento máximo. Nesse ponto, ele não cresce mais. Ele se encolhe do último segmento a partir do final e, em seguida, desaparece e reinicia. Esse tipo de movimento de linha é exatamente o que você precisa para criar campos de fluxo. Agora, uma maneira de implementá-lo. Eu crio 100 linhas. Esta é minha versão da tempestade de raios arco-íris gerada processualmente. Se você é iniciante e acompanhou até aqui, agora você é um corredor criativo com conhecimento de telas HTML. Parabéns, fique à vontade para adicionar este projeto, seu currículo on-line. 12. Degradês lineares: O Html Canvas oferece muitas ferramentas integradas diferentes que nos permitem modificar nossas animações. Acabamos de construir o efeito de tempestade de raios arco-íris. As linhas que estamos desenhando no Canvas são apenas formas. Deixe-me mostrar quatro maneiras muito diferentes de como você pode aprimorar o preenchimento e traçado de suas formas usando gradientes, imagens e sombras. A tela HTML oferece dois métodos para desenhar gradientes. Podemos usar o método de criação de gradiente linear. É muito simples de usar. Deixa eu te mostrar. Ele cria um gradiente ao longo de uma linha conectando dois conjuntos de coordenadas. Primeiros dois argumentos, passamos para ele nossas coordenadas x e y do ponto inicial. Quero que meu gradiente comece na coordenada zero. E eu queria que o ponto final estivesse nas coordenadas largura e altura da tela. Traçamos uma linha invisível daqui até aqui. O gradiente será desenhado ao longo dessa linha. Para trabalhar com gradientes, é útil salvá-los em uma variável. Eu o chamo, por exemplo, de gradiente um. Então eu pego essa variável e chamo método de adição de interrupção de cor embutido nela. Aqui, definimos offset e cor. Então, no deslocamento zero no início do gradiente, eu queria começar do rosa. Eu copio essa linha algumas vezes. Vamos começar com o offset 0.2. Na verdade, 0,3 será lido. 0,4 é laranja, 0,5 é amarelo. 0.6 será verde. 0,7, turquesa, 0,8 é violeta. Isso é o suficiente. Acho que pegaria essa declaração de estilo de traçado e a colocaria aqui depois de definirmos o gradiente. E vou configurá-lo como a variável que contém nosso gradiente linear recém-definido. Observe que não há aspas, apenas o nome da variável como este. Também preciso comentar a linha 33 para que nosso gradiente seja aplicado. Como você pode ver, estamos desenhando um gradiente linear da coordenada zero até a largura e a altura da tela. Eu crio 200 linhas. Essa é uma versão muito diferente da tempestade de raios arco-íris, não é? 13. Degradês radiais: Eu copio essa linha de código. Vou chamá-lo de gradiente de. Também criamos um método de gradiente radial. Este espera pelo menos seis argumentos, x e y do ponto central do círculo inicial interno e seu raio. Eu quero que o ponto central do círculo esteja no meio do Canvas. Portanto, a largura da tela vezes 0,5, a altura da tela vezes 0,5 e o raio será de 30 pixels. O círculo final também começará no meio da tela com um raio de 200. Eu dou para colorir paradas só para mostrar como é. Acho que você já entende esse conceito de qualquer maneira. Com um desvio de 0,4, teremos verde a partir de 0,6, será azul. Em seguida, defino o estilo do traçado para a ferramenta Gradient. Aqui. Eu posso mudar o valor do raio. Eu posso adicionar cor, pare aqui. Então, é assim que você usa o gradiente linear e radial. 14. Como preencher formas com um padrão: Como estamos preenchendo nossas formas com gradientes, podemos preenchê-las com um padrão. Esse padrão pode ser algo que desenhamos em uma tela fora da tela, mas também podemos usar uma imagem. Em index.HTML. Eu crio um elemento IMG. Eu dou a ele uma identificação da imagem padrão. Como fonte, eu normalmente usaria um caminho para esse arquivo de imagem, mas isso nos causaria problemas se executássemos nosso código localmente apenas a partir de uma pasta sem usar um servidor para evitar problemas de compartilhamento de recursos de origem cruzada Transformarei a imagem real em código base 64 e farei desse código parte do nosso arquivo HTML de índice. Quando eu fizer isso, a imagem será considerada da mesma origem em todos os cenários. Portanto, não preciso lidar com nada do site do servidor. Neste curso, quero me concentrar no desenvolvimento web de front-end. Eu preparei uma imagem que você pode baixar na seção de recursos abaixo, eu a fiz do mesmo tamanho da nossa tela. Também podemos usar sua própria imagem, se você quiser. Posso usar o JavaScript para transformar a imagem em uma string de dados de base 64 desenhando-a no Canvas e usando o método embutido de dois URLs de dados. Mas para simplificar, vou usar um site para fazer isso por mim, existem muitos sites que podem transformar imagens em código em segundos para nós, basta acessar o Google e pesquisar PNG com base em 64 frases. Vou escolher este link online PNG tools.com. Eu arrasto e solto a imagem que quero converter aqui e ela gera uma sequência de dados para mim. Temos que garantir que a string comece com a base 64. Se não cair, você clica nessa caixa de seleção para obter o formato correto. Eu copio todo esse bloco de código. É muito código, dependendo do tamanho da imagem que você está usando. Eu colo aqui dentro do argumento fonte, dentro como RC. No Visual Studio Code, posso ir para Exibir onde soltar para colocar essa linha de código extremamente longa em uma linha, facilitando a navegação nesse arquivo de código. Eu vou para o estilo CSS. Na verdade, salvei as alterações no index.HTML e você pode ver que estamos desenhando a imagem na página da web sem precisar do arquivo de imagem real. O código que acabamos de gerar substitui completamente o arquivo de imagem e contém todas as informações de pixels sobre essa imagem. Eu escondo a imagem com CSS usando seu ID display none. Ok, temos uma imagem que podemos usar. Então, nessa área, definimos os gradientes. Aqui, criaremos um padrão. Também é muito fácil. Vou precisar de uma referência ao elemento IMG que acabamos de criar no index.HTML. Eu crio uma variável que chamo de imagem padrão e apontei o JavaScript para o elemento IMG usando seu ID. Outra variável que chamo de padrão um é igual a ctx dot. E aqui usamos o método de criação de padrões embutido. Esse método funciona de forma muito semelhante aos dois métodos que usamos para criar gradientes. São necessários dois argumentos, imagem e repetição, e podemos então usá-los como fillStyle ou estilo de traçado para preencher nossas formas com essa imagem. Deixe-me mostrar como isso parece. A imagem a ser desenhada será a imagem padrão que acabamos de criar. E a regra da repetição não se repetirá. Agora eu simplesmente defino um estilo de traçado para o botão um. E aqui vamos nós. Podemos ver que nossas linhas agora estão preenchidas com uma imagem. Essa técnica pode ser usada como uma forma de revelar uma imagem, por exemplo, dependendo do tipo de aplicação ou efeito que você está criando, também podemos usar um bloco contínuo como imagem para criar um padrão repetitivo, que provavelmente é o que esse método foi projetado para fazer. Como objetivo principal, posso usar linhas mais largas para ver mais da imagem, por exemplo. 15. Melhore seus efeitos com sombras: Gosto de usar sombras do Canvas para obter um efeito 3D sutil em minhas formas. Eu disse sombra deslocada para dois pixels. Isso definirá a distância entre sombra e a forma horizontalmente. Deslocamento de sombra y, a distância vertical também será de dois pixels. A propósito, podem ser valores positivos ou negativos, dependendo do lado, em relação à forma que você deseja que a sombra tenha. A cor da sombra será branca. Isso nos fará com que essas rachaduras interessantes afetem ou reduzam o número de linhas. Bloco de cores de sombra. Eu posso voltar ao gradiente um, o gradiente linear. Agora podemos ver melhor o que a sombra está fazendo e como ela destaca as bordas. Se você tiver algum problema de desempenho e queda de FPS, a maneira mais rápida de corrigi-lo é reduzir o número de linhas que você está animando. E você também pode desativar essas sombras. Eu forneço uma largura para um valor menor. Nossa tempestade de raios arco-íris pode assumir várias formas, e acho que agora você tem muitas ferramentas para ajustá-la e torná-la sua. Vamos fazer algo completamente diferente com isso. Agora. Que tal, em vez de relâmpagos, eu quiser espirais. Vamos falar sobre trigonometria. Como sempre, talvez você queira criar uma cópia do seu código para salvar esse efeito para uma referência futura Faremos alterações radicais no código agora e o transformaremos transformaremos uma obra de arte generativa completamente diferente. 16. Trigonometria: A trigonometria tem tudo a ver com ângulos. Quero que cada objeto de linha tenha sua própria propriedade de ângulo. Então eu defino isso aqui. Para cada quadro de animação, aumentarei infinitamente esse valor de ângulo em 0,1. Esse valor representará radianos. Então, em vez de fazer esse efeito de iluminação aqui, aumentarei x pelo sinal de Masdar e passarei esse valor de ângulo cada vez maior. Isso criará um movimento horizontal para a esquerda e para a direita como este. análise e cada aumento no valor em metóxido apenas mapearão esses valores ao longo de uma onda senoidal. E se eu quiser que as ondas avancem mais para a esquerda e para a direita? Eu crio uma propriedade chamada curva pontilhada e a defino como 30. Por padrão, o método seno está alternando entre menos um e mais um. Se eu multiplicar esse valor por essa curva pontilhada, aumentaremos esse intervalo. E esse é o resultado. Eu quero linhas suaves, então eu removo essa parte do código aqui. Tente usar um valor diferente para a curva. Se você precisar de mais clareza sobre como esse valor afeta o movimento de nossas linhas. E se eu quisesse fazer uma curva para começar com um valor muito pequeno e aumentar gradualmente, a curva inicial seria 0,1. E Vc, a velocidade na qual será cada vez mais será de 0,25. Dentro do método de atualização para cada quadro de animação, eu queria aumentar a curva em VC assim. E quando as linhas recomeçarem, quero que o ângulo e a curva voltem a zero. Efeito interessante. Podemos fazer muitas coisas diferentes com ele agora. 17. Efeito de rabiscos de caos: E se eu também aumentasse a coordenada vertical y pelo seno do ângulo vezes a curva, obteremos esse estranho movimento para frente e para trás. Mas se eu usar cosseno em vez de seno e cosseno, trabalharemos juntos para mapear um caminho ao longo do raio de um círculo. E como a curva está aumentando à medida que a animação é executada, não temos Circle. Na verdade, temos espirais. Eu disse VC, velocidade da curva para um valor muito menor. Agora estamos desenhando espirais assim. Também posso fazer com que um valor aleatório entre -0,2 e mais 0,2 valores negativos se mova na direção oposta. Talvez eu também queira aleatorizar a rapidez com que o ângulo aumenta. Va, a velocidade do ângulo será um valor aleatório entre -0,25 e mais 0,25. Então eu o uso aqui em vez do valor codificado. A velocidade com que o ângulo está aumentando afetará o quão compacta é a curva rapidez com que ela se espalha. Isso é simetria. Quero adicionar um pouco de caos agora para esse projeto de arte simples, ou imaginar que alguém esteja desenhando essas lindas espirais simétricas. Mas a certa altura eles ficam com raiva e começam a rabiscar aleatoriamente e quebram a forma de espiral. Digamos que, se o cronômetro for maior que a metade da vida útil, a segunda metade do ciclo de vida da linha comece a multiplicar va por menos um, trocando-o para o valor oposto cada vez que um novo quadro de animação ocorre, cada vez que um novo segmento é desenhado. Isso quebrará a espiral em forma dessa. Temos um caminho que começa como uma espiral e depois se transforma em uma linha quebrada. Eu queria que a linha fosse cada vez mais quebrada. Precisamos de mais caos no final. Sim. Vamos mudar isso para 0,9. Na maioria das vezes, será simetria. últimos 10% serão um caos porque estamos modificando o valor va e não o estamos trazendo de volta à faixa original. As linhas param de fazer espirais da maneira que deveriam. À medida que as linhas são reiniciadas, também precisamos ser reiniciadas e valorizadas. Eu copio a linha 48 e colo aqui dentro do método de reinicialização. Bom. Começamos com simetria e terminamos em caos. Exatamente como eu em uma noite de sábado. Estamos constantemente calculando a vida útil vezes 0,9 porque esse cálculo acontece com muita frequência para facilitar a execução desse código pelo JavaScript e ajudar um pouco no desempenho. Podemos pré-calcular isso apenas uma vez no construtor da classe e, em seguida, usaremos esse valor pré-calculado aqui. Vou chamá-lo, por exemplo, ponto de interrupção de pontos e terá uma vida útil vezes 0,85. Então eu posso usar esse ponto de interrupção de pontos aqui. E em vez de calcular isso 60 vezes por segundo para cada objeto de linha, agora, estamos apenas calculando isso uma vez para cada linha no ponto em que cada objeto de linha é criado usando o construtor da classe. Eu faço as linhas mais largas. Eu disse fundo de tela para preto. Sim, esse é o efeito que eu queria. Eu comento nosso estilo de traçado na linha 54. Agora o traço é preto , então não vemos nada. Eu posso atribuí-lo à cor branca. Agora podemos ver novamente como as sombras dão um efeito 3D muito sutil. Eu disse número de linhas, 250. Tenha cuidado aqui. Pode ser demais para computadores mais antigos e você pode obter um FPS mais baixo. Eu faço 100, estou apenas experimentando agora. Posso definir o estilo do traçado como gradiente linear que definimos na linha 15 apenas para ver como é. Que tal eu usar gradiente radial? Para este, eu definitivamente deveria escolher cores diferentes para deixá-lo bonito. Também posso usar o padrão de imagem aqui novamente. Interessante. Você já viu esse ótimo método de padrão sendo usado antes ou é sua primeira vez? Agora você tem todas as ferramentas necessárias para criar campos de fluxo lindos e totalmente animados, confira os links na descrição e participe de uma aula avançada em que usamos as técnicas que aprendemos hoje para criar uma arte mais generativa. 18. O que é um campo de fluxo: Aqui está uma grade de ângulos. Também podemos chamá-lo de campo vetorial se adicionarmos um sistema de partículas em cima dele e fizermos com que as partículas fluam pela grade. Seu movimento é influenciado pelo vetor de campo. A direção e a velocidade do movimento serão influenciadas pelo valor do ângulo armazenado na célula sobre a qual cada partícula está se movendo atualmente. Esta aula é para pessoas criativas que desejam entender como o código funciona nos bastidores. Não se esqueça de verificar a seção de recursos para baixar o código-fonte se quiser compará-lo com o meu. Incluí vários downloads de código-fonte em pontos-chave do projeto à medida que avançamos com a aula, caso você queira inspecionar meu código e compará-lo com o seu. Eu criei uma página da web genérica com o elemento de tela HTML nela. Eu vinculei aos arquivos style.css e script.js. Eu fiz uma redefinição global de CSS e dei ao elemento canvas um fundo preto. 19. Configuração de tela HTML: Depois de uma configuração simples de HTML e CSS, o resto do projeto será tratado por JavaScript aqui dentro do arquivo script.js. Como sempre, preciso configurar minha variável personalizada do Canvas chamada cannabis will be document, obter elemento por ID e ID que dei, era canvas one. O contexto Ctx é aquele ponto variável de tela getContext. E eu passo para o para criar uma instância do objeto de contexto de renderização em tela. Agora, o CTX contém todos os métodos e propriedades de desenho integrados métodos e propriedades de desenho que qualquer navegador da web pode entender. Eu quero que você tenha um efeito de tela cheia hoje. Portanto, a largura será a janela em uma rave e a altura da tela será a janela na altura dela. Não tenho certeza se você consegue ver isso, mas fazer isso gerou barras de rolagem para minha página da web. Eu não quero que eles sejam tão fáceis de resolver é dar uma posição absoluta ao elemento da tela , assim, boa. Então, toda essa área preta é nossa tela, nossa prancheta de desenho. Eu posso usar a variável ctx da ferramenta de linha para desenhar algo. Agora, se eu consola o Gate, podemos ver as configurações padrão. exemplo, eu posso ver que o tipo padrão de fillStyle é preto para garantir que as formas que desenhamos sejam visíveis contra o fundo preto. Eu disse FillStyle para branco. 20. Desenhando formas em tela: Aqui embaixo, podemos ver todos os métodos de desenho embutidos no Canvas, por exemplo , o método de arco, que pode ser usado para criar um arco ou um círculo completo. Se tivéssemos mais formas no Canvas, terei que chamar begin path. Mas agora eu posso pular isso. E digamos que eu queira um círculo com um ponto central nas coordenadas 100 horizontalmente da borda esquerda do Canvas, 100 verticalmente da borda superior. O raio do círculo será de 50 pixels. O ângulo inicial do arco será 0 rad. E como eu quero desenhar um círculo completo, o ângulo final será math.pi vezes dois, que é aproximadamente 6,28 rad ou 360 graus. Círculo completo. O método Arc funciona com um caminho, então ele não renderiza nada diretamente na cannabis. Ele apenas posicionou um caminho invisível. Podemos escolher traçar esse caminho ou preencher essa forma com cores. Então eu chamo um método de preenchimento embutido como este. Eu posso mover o ponto central do círculo. Eu posso mudar o raio. Posso até mudar o ângulo final ou o ângulo inicial para obter uma forma diferente. Ok, então nosso Canvas está configurado e nós o testamos desenhando uma forma. Nesta área, manterei minhas configurações globais do Canvas para manter nosso código organizado. Hoje, estamos construindo um campo de fluxo animado. Será feito de linhas individuais. Então, como desenhamos uma linha simples no Canvas? Começamos com Colin, método embutido e iniciamos o caminho. Isso iniciará um novo caminho, além de revestir todos os caminhos anteriores. Se houver algum, chamamos moved to method para definir as coordenadas iniciais x e y da linha. Chamamos um método line to para definir o final em coordenadas. Ou podemos entrelaçar várias linhas para criar uma forma mais complexa, que é o que faremos hoje. O mesmo que o método do arco. Vá para a linha final dos dois métodos mencionados acima. Eles não renderizam nada diretamente no Canvas. Agora temos que escolher se queremos traçar o caminho ou se queremos preencher essa forma com cor, chamarei o método de traçado embutido para desenhar o caminho. estilo de traçado padrão é preto, portanto, não é visível contra o fundo preto. Eu subi até aqui e disse estilo de traço para branco. Agora podemos ver que estamos desenhando uma linha a partir das coordenadas 100, 202, 400, 500. Por padrão, a linha tem um pixel de largura. Posso usar a propriedade de largura da linha para defini-la para dez pixels ou 100. Também posso usar a lacuna de linha e configurá-la como arredondada, por exemplo. 21. Programação orientada a objetos no JavaScript: Ok, então é assim que desenhamos e estilizamos linhas na tela HTML. Isso é tudo o que precisamos saber para criar uma grande variedade de efeitos. Eu queria criar muitas linhas animadas que fluíssem em torno do nosso Canvas. Vou usar a classe JavaScript chamada particle. Assim. Cada partícula se moverá e conectaremos suas posições com uma linha. As classes Javascript são modelos para criar muitos objetos semelhantes. E estamos prestes a construir o chamado sistema de partículas feito de muitas partículas. Eu também terei uma aula chamada efeito. Isso poderia ter sido apenas um objeto simples porque teremos apenas uma instância dessa classe. Será o cérebro principal da nossa base de código. Portanto, temos a classe de partículas, um modelo que usaremos sempre que precisarmos criar um novo objeto de partícula. E teremos uma classe de afeto que gerenciará todo o efeito, todas as partículas de uma só vez. Estou usando classes e programação orientada a objetos para manter nosso código limpo, bem organizado e fácil de ler. Este é um tutorial para iniciantes, então eu quero que tudo seja limpo e o mais fácil de entender possível. É meu objetivo principal. turma afetada precisará estar ciente do espaço disponível para cannabis. Portanto, o construtor espera que a largura e a altura venham como argumentos externos quando uma instância dessa classe é criada usando a nova palavra-chave interna Eu converti esses argumentos em propriedades de classe. Pegue with pass como argumento aqui e converta-o em propriedade de largura nesta instância da classe de afeto, o mesmo para altura. A classe Affect terá o método inicializado. Esse método será executado apenas uma vez para configurar tudo. Teremos essa propriedade de partículas de cachorro. Essa será uma matriz que contém todos os objetos de partículas atualmente ativos. Então, quando inicializamos esse efeito, queremos pegar essa matriz de partículas de carga e usar o método embutido de push de matriz para inserir uma nova partícula na matriz. Essa partícula será criada usando a classe que definimos na linha 11. Então, vamos escrever essa classe de partículas agora. Cada partícula também precisará estar ciente da largura e altura da tela, pois precisa saber quando ela se move para fora da área da tela para manter nosso código modular em vez do tamanho booleano da tela nas linhas 3.4 Vou pegar esse valor da classe de efeitos principal. Eu queria acessar essas propriedades a partir das linhas 920. Eu darei acesso à classe de partículas a toda a classe de efeitos. construtor da classe de partículas espera um efeito como argumento e, por dentro, o convertemos em uma propriedade de classe. Então, aqui estamos apontando para o objeto de efeito principal. Lembre-se de que objetos em JavaScript são chamados para referenciar os tipos de dados. Não estamos criando uma cópia do objeto de efeito. Toda vez que criamos uma nova partícula, estamos apenas apontando para o mesmo espaço na memória que contém a classe de efeito de todos os objetos de partículas. Dessa forma, as partículas têm acesso a todos os métodos e propriedades do vidro de efeito principal. Além disso, se alguma dessas propriedades atualizada porque estamos apenas apontando para esse objeto, qualquer alteração no objeto de efeito será imediatamente visível nos objetos de partículas, o que será muito útil para nós hoje. Como eu disse antes, teremos um objeto de efeito para gerenciar tudo. E teremos muitas partículas, centenas ou talvez milhares. Vamos ver no que acontece. Cada partícula terá coordenadas iniciais x e y. coordenada x horizontal será um valor aleatório entre zero e esse efeito de ponto da linha 13 da largura do ponto, estamos acessando essa propriedade a partir da linha 20. coordenada vertical y será um valor aleatório entre zero e a altura do ponto com efeito de ponto. Para evitar valores de subpixel, é uma boa prática usar números inteiros, números inteiros sem pontos decimais , envolvendo-os em Math.floor Isso arredondará o valor para o número inteiro mais baixo mais próximo. Cada partícula terá um método de sorteio público. Esse método espera contextos como argumento para especificar em que tipo de nós gostaríamos de nos basear. Eu passo isso como um argumento como esse para manter nosso código mais modular e menos dependente do ambiente externo. Em seguida, pegamos esse contexto e chamamos o método de preenchimento de retângulo embutido. O método de preenchimento do retângulo é muito simples. Ele apenas pegará essas coordenadas X e Y aleatórias que acabamos de definir e desenhará um retângulo lá. Sua largura e altura serão, por exemplo, dez vezes dez pixels. Temos nossa classe de partículas e temos a classe de afeto. Eu queria criar uma instância da classe de efeito. Eu crio uma variável personalizada que chamo, por exemplo , de efeito, e ela será igual a um novo efeito como este. A nova palavra-chave procurará uma classe com esse nome. Ele o encontra aqui e acionará seu construtor de classes online 23. Podemos ver que o efeito espera largura e altura como argumentos. Então, passamos a largura da tela a partir da linha três. E mais ou menos a altura da linha quatro, assim. Agora, posso entender que isso afeta a variável e chamar o método init que definimos na linha 28. O método init pegará a matriz de partículas e colocará um novo objeto de partícula na matriz. Recebemos um erro porque aqui na linha 12, você pode ver que o construtor da classe de partículas espera uma referência à classe de efeito principal como argumento e, em seguida, usa essa referência para acessar as propriedades de largura e altura do Canvas. Como estamos criando essa partícula dentro da própria classe de efeito, eu passo essa palavra-chave, que nesta área se refere a toda a classe de efeito. Bom. Então, depois de criarmos uma instância de vidro de efeito, e depois de chamarmos esse método de inicialização, espero que a matriz de partículas da linha 26 contenha um objeto de partícula. Eu consola o vidro de efeito para verificar. Eu posso ver o objeto de efeito. Tem propriedades de largura e altura. E se eu abrir essa matriz de partículas, posso ver que há um objeto de partícula dentro. Eu verifico se todas as propriedades têm valores. Se eu ver indefinido ou não em algum lugar, isso indicaria um problema. Tudo está bem aqui. Agora, preciso de uma maneira de realmente desenhar meu efeito no Canvas. Vou dar a ele outro método que chamo, por exemplo, renderizar dentro do nosso ciclo sobre todos os objetos de partículas dentro da matriz de partículas usando matriz para cada método. Por enquanto, sabemos que há apenas um objeto de partícula em seu interior. Para cada objeto de partícula dentro da matriz de partículas, chamo seu método de retirada associado. Definimos esse método de desenho na linha 17 e podemos ver que ele espera contexto como argumento. Então, eu pego o método render e chamo de que precisamos desse contexto. Então eu pego CTX da linha dois. Eu passo para renderizar. Dentro da renderização, isso será esperado como contexto. E passamos essa referência de contexto para o método de desenho porque sabemos que ela é esperada na linha 17. A partir daí, o método de preenchimento do retângulo é chamado e nossa partícula é desenhada. Bom. Posso alterar a largura e altura ao atualizar a janela do navegador, coordenadas x e y das linhas 14.15 são aleatórias e a partícula é desenhada. 22. Desenho de sistemas de partículas: A principal classe de efeito que eu crio é uma propriedade que chamo de número de partículas. O método inicializado será executado, só queremos configurar nosso efeito interno. Vou criar essas 50 partículas. Eu posso fazer isso usando um loop for. Ele será executado 50 vezes e, toda vez que for executado, pegará uma matriz de partículas e empurrará uma nova partícula com coordenadas x e y aleatórias para dentro. E é assim que você cria um sistema de partículas simples. Se quiser, você pode salvar esse código como um padrão em uma pasta diferente, pois você pode usá-lo para muitos experimentos, efeitos e obras de arte generativas diferentes . Estou chamando o método init daqui no primeiro carregamento da página. Também posso remover esse código e chamá-lo de “ .in” de dentro do construtor da classe de efeito. Porque quando criamos uma instância de uma classe usando a nova palavra-chave, o construtor executará todo o código no blueprint linha por linha. Podemos tirar proveito desse comportamento colocando aqui qualquer código que queiramos executar no mesmo ponto em que uma instância dessa classe é criada. 23. Animando sistemas de partículas: Estamos construindo um campo de fluxo. Quero que essas partículas se movam e deixem trilhas e linhas atrás delas. Vamos animar essa velocidade X, a velocidade horizontal será uma. As partículas se moverão um pixel por quadro de animação na direção positiva. No eixo x horizontal, eles se moverão para a direita. Velocidade. Y também será um pixel por quadro. Direção positiva no eixo y vertical significa para baixo. Como essas duas forças serão aplicadas à partícula ao mesmo tempo, eu esperava que as partículas se movessem em direção ao canto inferior direito do Canvas. Vamos ver. O movimento será tratado dentro do método de atualização. Esse método definirá uma única etapa na animação. E quando chamamos esse método de atualização 62 vezes por segundo, ele criará uma ilusão de movimento. Para cada quadro de animação, quero aumentar a posição horizontal x dessa partícula da linha 14 pelo valor da velocidade x da linha 16. Eu também quero aumentar a posição vertical em velocidade. Por quê? Aqui dentro da renderização, à medida que percorremos todas as partículas, acionamos o método draw e também chamamos o método de atualização que acabamos de escrever. Isso é chamado, só quer , então não há movimento. E ele deve chamar esse método de renderização repetidamente. Eu queria desenhar partículas, atualizar suas posições, desenhá-las novamente nessas posições atualizadas, atualizá-las novamente, desenhá-las novamente e assim por diante. Chamando isso repetidamente, criaremos animação, uma ilusão de movimento. Precisamos de um loop de animação. Eu crio uma função personalizada que chamo, por exemplo, animar de dentro de nossa renderização de chamada para desenhar e atualizar todas as partículas. E então eu chamo quadro e o método de animação de solicitação integrados. Eu passo, animo o nome de sua função principal. Então, o animate é executado, a renderização é chamada de partículas, é desenhada e atualizada e, em seguida, solicita o quadro de animação e o método chamam animate. Novamente, temos um método de quadro de animação de solicitação de loop foi projetado para essa finalidade e tem recursos especiais, que foi projetado para essa finalidade e tem recursos especiais, como tudo isso, para gerar os registros de data e hora para nós. E também se ajusta à taxa de atualização da tela. Eu tenho uma tela normal, então minhas animações são executadas a 60 quadros por segundo. Se você tiver um jogo e uma tela com alta taxa de atualização, suas animações serão executadas mais rapidamente. Você pode usar facilmente o quadro de animação de solicitação e seu carimbo de data/hora gerado automaticamente para definir a velocidade de animação desejada. Agora tudo está pronto e eu posso chamar de animate nossa expectativa de que todas as partículas se movam um pixel para a direita e um pixel para baixo até o quadro de animação. Eles estão deixando rastros porque podemos ver pinturas antigas, suas posições anteriores. Se eu quiser ver apenas o quadro de animação atual, preciso excluir o Canvas entre cada quadro usando o método de retângulo transparente. Quero limpar toda a tela, das coordenadas zero a zero até a largura e a altura da tela. Bom. Estamos animando. Eu mudo a velocidade. A relação entre velocidade x e velocidade. Por quê? Definiremos a direção e a velocidade do movimento. Também podemos randomizar a velocidade de cada partícula. Que tal um valor aleatório entre -2,5 e mais 2,5 menos o valor se mover para a esquerda, mais os valores para a direita. No eixo vertical, valores negativos moverão as partículas para cima. Valores positivos moverão as partículas para baixo. A razão entre a velocidade aleatória x e a velocidade. Por que determinará a direção final do movimento? E agora as partículas se movem em todas as direções possíveis. Eu posso tornar as partículas menores. 24. Desenhando linhas e trilhas: Na verdade, eu quero desenhar linhas. Eu chamo o método Big Bath para dizer JavaScript que eu queria iniciar um novo caminho. Conforme a partícula se move pelo Canvas para cada quadro de animação, ela atualizará suas posições x e y. E vou acompanhar essas posições como objetos simples com propriedades x e y dentro da matriz do histórico. Inicialmente, cada partícula receberá uma posição aleatória x e y em algum lugar dentro da área da tela. E usamos esses valores como o primeiro objeto, o primeiro elemento com um índice zero dentro da matriz do histórico. O ponto inicial da linha será salvo ao mover para o método. Queremos começar com as coordenadas x e y do primeiro objeto dentro do objeto da matriz de histórico com um índice zero. Em seguida, criamos um loop for. Ele será executado enquanto houver mais elementos na matriz do histórico. Para cada objeto, todos esses objetos têm essa aparência. Para cada objeto de posição dentro da matriz histórica, tomaremos as coordenadas x e y de um objeto nesse índice. À medida que o for-loop percorre a matriz, passamos suas coordenadas x e y para alinhar dois métodos. Então, ponto de partida da linha. Em seguida, percorremos todas as posições dentro da matriz histórica e as conectamos com uma linha. Em seguida, traçamos esse caminho para realmente desenhá-lo no Canvas. Agora preciso ter certeza de que as posições estão sendo adicionadas à matriz histórica à medida que a partícula viaja. Sempre que atualizamos a posição das partículas, pegamos essa matriz de histórico de pontos e inserimos um objeto como esse com esses valores de x e y atualizados. Bom, parece que é apenas uma linha reta, mas na verdade é uma forma feita de muitos segmentos de linha menores. Posso, por exemplo, fazer com que ele oscile adicionando um valor aleatório entre -1,5 e mais 1,5. Isso deve deixar mais claro visualmente que essas linhas são feitas de segmentos. Eu posso fazer a mesma coisa verticalmente. Eu posso aumentar o intervalo aleatório que pode ser de -2,5 para mais 2,5. Eu posso aumentar ainda mais o alcance. Um valor aleatório entre -7,5 e mais 7,5. Finalmente, isso está começando a parecer interessante. Certo? Agora. Eles crescem infinitamente em linhas. E se eu quiser definir o comprimento máximo de uma linha? Nesse caso, isso significará o número máximo de segmentos. Dentro do método de atualização. Eu digo que se o comprimento da matriz histórica for maior que maxlength, chame o método embutido de mudança de matriz. Portanto, temos dois métodos de matriz aqui. O método push adiciona um novo elemento ao final de uma matriz. O método Shift remove um elemento desde o início. Porque estamos adicionando novos elementos ao final da matriz. O método Shift remove o segmento mais antigo. Então, as companhias aéreas circulam assim. Eles podem parecer pequenas criaturas ao microscópio. Eu poderia simplesmente dar a eles um pouco de IA e transformar isso em um jogo. Posso aumentar o comprimento máximo da linha para segmentos de 100. Ou eu posso fazer um valor aleatório 10-110. Agora, alguns deles têm caudas curtas e outros têm caudas muito longas. 25. Padrões de movimento com trigonometria: Também posso aplicar a trigonometria, cuja partícula terá uma propriedade angular que inicialmente começará em zero. Para cada quadro de animação, aumentarei o ângulo em um pequeno valor. O valor do ângulo está em radianos. Então, posso passar esse ângulo cada vez maior para o signo de Martha, que mapeará automaticamente esses valores ao longo de uma onda senoidal. Isso dará à coordenada horizontal uma emoção de onda irregular. Veja o que acontece quando eu faço isso também na posição vertical. Em vez de adicionar aqui, tento multiplicar. Eu faço isso tanto para a combinação de seno quanto de cosseno. Vamos mapear as posições ao longo do raio de um círculo, multiplicá-lo por um valor como esse aumentará o raio. Você pode tentar usar diferentes combinações de valores e aplicar operações diferentes se quiser experimentar Há muitas coisas que podem ser feitas aqui. Basicamente, construímos um sistema de partículas em que cada partícula desenha uma linha atrás dela. Eu comento uma linha 69 por um tempo. 26. Criando um campo de vetor: Agora, meu objetivo é fazer com que essas linhas percorram a tela seguindo uma ordem específica para criar um efeito de campo de fluxo. O campo de fluxo é baseado em uma grade de ângulos. Cada célula na grade armazena um valor de ângulo. E cada célula nessa grade no campo de fluxo tem um relacionamento com as células vizinhas. Eles não são aleatórios. Eles aumentam ou diminuem gradualmente. E à medida que a partícula viaja pela grade, célula por célula, velocidade da partícula e a direção do movimento são influenciadas por esses valores de ângulo, criando um padrão de movimento. algoritmo muito comum para gerar valores de ângulo para um campo de fluxo é o ruído Perlin. Ele cria um ruído de gradiente que muda gradualmente os valores de forma aleatória. O efeito resultante parece muito natural e pode ser usado para gerar texturas para serina gerada processualmente ou muitas outras coisas. Hoje vamos gerar um campo de fluxo em espiral onde usamos valores de seno e cosseno e os anexamos às coordenadas vertical e horizontal de cada ponto de cada célula. Isso cria um belo padrão de repetição simétrica. Poderemos ampliar e reduzir o padrão para obter resultados muito diferentes. Vamos analisá-lo passo a passo e ficará claro do que estou falando à medida que o construímos. Nosso objetivo agora é criar uma grade que divida toda a tela em células individuais. Digamos que eu queira vender o tamanho cada célula para 20 vezes 20 pixels. Isso dividirá a tela em linhas e colunas. O número de linhas e colunas dependerá da largura e altura do Canvas e desse tamanho de célula. Eu poderia calcular o número de linhas e colunas aqui. Mas como eu quero que esse efeito seja responsivo, vou calcular isso dentro do método init. Podemos então chamar esse método init toda vez que um evento de redimensionamento acontece para recalcular corretamente toda a grade do campo de fluxo. Esse campo de fluxo de carga será uma matriz que contém valores de ângulo para células individuais na grade. O número de linhas será a altura da área da tela dividida pelo tamanho da célula. O número de colunas será dividido por onda pelo tamanho da célula. Também definiremos o campo de fluxo como uma matriz vazia, caso esse método de inicialização seja chamado durante o redimensionamento do Canvas. Dessa forma, todos os valores antigos serão excluídos e poderemos recalcular os novos valores. Agora, eu quero percorrer essa grade sempre que houver algo envolvido, a maneira mais fácil de lidar com isso é com dois aninhados para loops, o externo para loop, o ciclo sobre a grade, linha por linha a partir da linha zero, desde que haja mais linhas. O loop interno percorrerá cada linha da esquerda para a direita. Então, entramos no loop externo, estamos na linha zero. Entramos no circuito interno e percorremos as células dessa linha, uma a uma. Chegamos ao fim, saímos do circuito interno. Entramos no loop externo, Y aumenta e entramos na próxima linha. Novamente. Percorremos todas as posições daquela linha, uma por uma. Repetimos esse processo linha por linha até cobrirmos todo o Canvas. Cada vez que entramos em uma nova célula, criamos um valor de ângulo. Podemos fazer coisas diferentes aqui. Vou simplesmente vincular as coordenadas x e y ao seno e cosseno para criar um padrão espiral. Sabemos que, se passarmos um aumento no valor do ângulo para seno ou cosseno, esses métodos mapearão esse aumento nos valores ao longo de uma onda. Nesse caso, esses valores crescentes são as posições x e y das células na grade. Então, à medida que nos movemos ao longo da grade, criamos espirais e curvas. Toda vez que geramos um novo valor de ângulo, nós o inserimos na matriz do campo de fluxo. Lembre-se de que estamos pedalando, integrando linha por linha, gerando esses valores, mas os estamos armazenando em uma matriz como uma única sequência contínua de valores. Precisamos ter isso em mente quando precisarmos extrair esses valores de ângulo novamente, para combiná-los corretamente com as posições x e y atuais das partículas. Portanto, neste ponto, a matriz do campo de fluxo deve ser preenchida com valores de ângulo. Então, vamos registrar isso no console. Na verdade, estou fazendo login no console depois de cada linha, eu deveria ter colocado o log do console aqui depois de tudo pronto, mas isso não importa. Podemos ver que os valores dos ângulos estão sendo gerados. Perfeito. Então, percorremos a tela, integramos e, para cada célula nessa grade, geramos o valor do ângulo e iniciamos todos esses valores angulares dentro da matriz do campo de fluxo. Como passamos esse aumento gradual nos valores de x e y para seno e cosseno, criamos um lindo padrão simétrico. O padrão será revelado quando desenharmos o campo de fluxo. Então, vamos fazer isso. Já temos partículas que se movem sobre o Canvas e arrastam linhas atrás delas. Atualmente, estamos usando essa lógica para movê-los. Vamos afastar tudo isso e alterar completamente esse código no método de atualização. Aqui, quero que as partículas se movam e a direção de seu movimento dependerá da posição da partícula à medida que ela viaja por diferentes células no campo de fluxo. Os valores do ângulo no campo de fluxo mudam célula por célula. E esse ângulo determinará o movimento da partícula que está fluindo atualmente sobre aquela célula. Há muitas maneiras diferentes de fazer isso. Criarei uma variável x temporária auxiliar, que será igual à exposição atual das partículas dividida pelo tamanho da célula. Basicamente, estou dizendo quantas células em nossa grade a partir da borda esquerda do Canvas, essa partícula está atualmente, em qual coluna estamos atualmente. Lembre-se de que o tamanho da célula foi definido como 20. Eu quero números inteiros aqui, então vou arredondar o valor para baixo. variável y auxiliar será a posição y atual das partículas dividida pelo tamanho da célula. Quantas células? Do topo, estamos em qual linha. Agora posso usar esses valores para mapear as coordenadas x e y de uma partícula para um índice na matriz do campo de fluxo. Basicamente, tenho uma partícula com certas posições x e y em uma grade bidimensional. E eu tenho uma matriz que representa essa grade, mas é apenas um longo conjunto de números. Então, o que estou tentando fazer agora é mapear as posições x e y para esse índice para que eu possa extrair o valor correto do ângulo. A posição vertical e horizontal atual das nanopartículas da grade . E eu sei sobre qual coluna e linha na grade do campo de fluxo ela está se movendo atualmente. Agora eu preciso usar esse valor de coluna e linha para obter o valor do ângulo da célula da matriz do campo de fluxo. É um pouco complicado de visualizar se você for iniciante, então não se preocupe muito para obter o índice de disposição de uma então não se preocupe muito para obter matriz cheia de fluido Eu pego o número da linha que calculamos aqui e o multiplico pelo número de colunas que calculam esse bloco. As linhas, termos células por linha basicamente precisam saber em qual célula estamos atualmente porque adicionamos um valor de ângulo por célula na matriz do campo de fluxo. Em seguida, adicionamos quantas células estivermos na linha atual na grade, desta forma. Isso nos fornece um índice dentro da matriz de campo de fluxo que contém o valor do ângulo da célula sobre a qual estamos movendo atualmente. Em seguida, definimos o valor do ângulo dessa partícula para o índice dentro da matriz de campo de fluxo que acabamos de calcular. 27. Como criar um campo de fluxo: Agora temos várias opções diferentes de como usá-lo para obter padrões diferentes. Primeiro, definirei a velocidade x dois cossenos do ângulo. velocidade y será o sinal do mesmo valor que acabamos de extrair online 35. Em seguida, tomo a posição horizontal da tela de partículas e a aumento nesse novo valor de velocidade. E eu faço o mesmo para a posição vertical, aumentando-a pela velocidade vertical. Eu excluo esse código. Então nos dividimos em uma grade invisível. Cada célula tem 20 vezes 20 pixels e tem um valor de ângulo específico. Calculamos em qual coluna e em qual linha dessa grade a partícula está se movendo no momento. Mapeamos o valor da coluna e da linha para indexar na matriz do campo de fluxo para extrair o valor do ângulo que pertence à célula de que precisamos, aumentamos a velocidade x pelo cosseno dessa velocidade angular. Por que por sinal? Isso nos dará uma direção de movimento dependendo desse ângulo. Em seguida, aumentamos a posição X e Y das partículas. Por essas velocidades. Colocamos essa nova posição de partícula dentro matrizes históricas para que possamos animar sua cauda, a linha que cada partícula traça sozinha. Se o comprimento da linha for maior que o comprimento máximo, removemos o segmento mais antigo. Eu renderizo sem comentários para ver qual movimento obtemos. Parece que não, mas já temos um campo de fluxo ativo com padrão espiral de seno e cosseno. Estamos apenas afastados muito longe disso. Fará mais sentido se jogarmos com o código agora. Portanto, a ideia básica é que, analisando um valor de ângulo cada vez maior em seno e cosseno, faremos com que os valores circulem periodicamente entre menos um e mais um. Usamos as posições X e Y de cada partícula à medida que esses aumentam nos valores dos ângulos. Portanto, o padrão será vinculado às coordenadas dessa forma. Eu fecho isso entre colchetes e multiplico por dois. Isso aumentará o raio da curva. Eu removo o retângulo. Eu só queria linhas. Eu faço com que o comprimento máximo da linha seja um valor aleatório, 10-210 segmentos. Eu posso usar valores diferentes aqui. Vamos aumentar o número de partículas para que possamos ver melhor o padrão. Veja o que acontece se eu aumentar lentamente esse valor, 0,5. Eu posso ir muito mais alto do que isso. Acho que por volta das dez. Vamos colocar esse valor em variável, em uma propriedade de classe. Eu chamo isso de curva pontilhada. Eu vou te mostrar por que eu chamo isso de curva em um minuto. Ficará claro. Eu uso essa propriedade aqui. Ok? Também posso multiplicar x e y por um valor. Se os valores forem iguais, obteremos um zoom simétrico nesse padrão. Ainda não é totalmente óbvio, mas um padrão claro surgirá disso. Tenha paciência comigo. Quero que esses valores sejam idênticos em termos de simetria e vou colocá-los em uma propriedade de classe. Eu chamo isso de Zoom. Eu disse isso no zoom até o ponto zero. Lembre-se de que zoom curvo também está conectado ao tamanho da célula, pois a forma como vinculamos a curva seno e cosseno a uma posição em que uma grande mudança no tamanho da célula afetará o padrão. Isso afetará o Zoom. Acho que neste momento já podemos chamá-lo de campo de fluxo. Aumente lentamente o zoom para mostrar como esse valor afeta o padrão. Eu posso realmente entrar no padrão, ampliar de perto e lentamente, eu diminuo o zoom. Ainda assim. Não acho óbvio qual é o padrão. Vamos até aqui para o construtor de classes de partículas. Posso remover esses valores iniciais de velocidade x e velocidade. Por quê? Porque eles são imediatamente substituídos aqui dentro do método de atualização. Quero que cada linha se mova em uma velocidade diferente. Então, darei a cada partícula uma propriedade modificadora de velocidade, que será um número inteiro aleatório de 1 a 3. Aqui embaixo, eu multiplico velocidade x e velocidade. Por que usar esse modificador de velocidade. Agora, algumas linhas se movem mais devagar ou mais rápido. Vamos aumentar a velocidade. Modifique, organize. Para mostrar claramente como curva e o zoom afetam o padrão. Precisamos que as linhas sejam reiniciadas quando terminarem a sequência de animação. Eu crio um método que chamo, por exemplo, reset. Quando reiniciei, eu disse que x e y coordenam para uma nova posição aleatória em algum lugar ao redor da tela. E também preciso definir a matriz do histórico para esses novos valores como a posição inicial com um índice zero. No momento, a lista infinita de maiores movimentos está em algum lugar distante da tela. Vou criar uma propriedade que chamo, por exemplo, timer. Será o comprimento máximo da linha vezes dois. Para cada toque de animação, diminuirei o cronômetro em um. O temporizador começa com um valor igual a maxlength. Os termos diminuem em um para cada quadro de animação. Enquanto o cronômetro for maior ou igual a um, animaremos a linha e faremos rastejar como uma poeira. Já. Quando o cronômetro atingir um, as linhas congelarão em um lugar assim. Neste ponto, queremos uma instrução else seja executada, que começará a remover segmentos antigos de cada linha, um por um, fazendo com que a linha desapareça do final. Eu faço isso chamando shift na matriz do histórico. Isso nos dará um erro quando removermos tudo da matriz do histórico, mas ainda tentarmos desenhá-la. Então, vou apenas executar esta outra declaração. Se a matriz de histórico contiver mais de um elemento, somente então remova todos os segmentos da linha. As linhas fluem ao redor. Quando o cronômetro chega a zero, começamos a remover todos os segmentos até que não haja mais segmentos. Perfeito. Nesse ponto, quero que a linha seja reiniciada e repita esse ciclo de animação novamente. Caso contrário, chame esse método de redefinição de pontos que acabamos de definir na linha 56. Ok, não está funcionando porque eu também preciso redefinir o cronômetro para seu valor original. Parabéns, você constrói um campo de fluxo. Essa é uma base de código muito sólida e podemos fazer muitas coisas com ela. Finalmente chegou a hora de usar corretamente o Curve e o zoom para mostrar o padrão do qual eu estava falando. 28. Experimentos de campo de fluxo: Como dissemos, o ruído de Berlim criará uma aparência natural no padrão de ruído em gradiente. Estamos calculando valores de ângulo para nosso campo de fluxo online 85 usando trigonometria. Então, mesmo que não pareça, agora, esse é um padrão matemático muito simétrico que se repete infinitamente em todas as direções. Deixe-me mostrar o que quero dizer. Veja o que acontece quando eu aumento o valor da curva. Gosto muito de ver esse efeito. Há algo muito descontraído e, sobre isso, acho que agora você pode ver um pouco que temos um padrão repetitivo. Eu mudo o zoom e me afasto dele para ver claramente a repetição. Também posso ampliar bem o padrão e observamos apenas uma pequena parte dele. Parece que o fluxo é realmente aleatório, mas sabemos que não é. Vou aumentar o número de partículas. Meu computador pode lidar com isso, mas você deve ajustar o número de partículas para garantir que seu computador possa animar isso sem problemas, para que você não precise usar 2000 partículas aqui. Experimente valores diferentes e veja. Eu não recomendo ir muito além de 2000, a menos que você tenha um computador muito poderoso. Os campos de fluxo são um efeito muito bonito. E agora você sabe como construir um sozinho. Estamos apenas brincando com o padrão de seno e cosseno aqui, mas podemos usar esse código para mudar o fluxo e fazer com que ele siga muitos padrões diferentes. Veja o que acontece quando eu mudo a curva de valor. À medida que o valor aumenta, um padrão em espiral começará a surgir. Esse joelho está um pouco mais alto. Ele começará a se curvar em espiral aqui. E à medida que eu aumento o valor, ele aumenta cada vez mais. Isso criará uma forma de caracol em espiral se subirmos o suficiente. Agora está se tornando mais óbvio. E ainda mais, a curva simplesmente gira em espiral sobre si mesma. Interessante, não é? Então, agora eu acho que é muito óbvio como a curva afeta a forma espiral do campo de fluxo. Esse padrão se repete sem parar em todas as direções e podemos ampliá-lo e diminuí-lo alterando os valores que usamos como zoom de pontos na linha 75 Posso ampliar bem próximo ao padrão. E à medida que eu aumento esse valor, estamos lentamente diminuindo o zoom. Neste ponto, podemos ver a natureza repetida desse padrão. Como presumimos o suficiente. Eu vou ainda mais longe. Eu posso fazer com que ela cresça mais. Você vê como o padrão é irregular e não é muito liso. Isso está expondo a natureza em forma de grade do campo de fluxo, já que o ângulo só muda a cada 20 pixels Posso reduzir o tamanho da célula para tornar o fluxo mais suave. E basicamente cortando a cannabis em pedaços menores, cinco vezes cinco pixels. Como agora podemos encaixar mais colunas na área de tela disponível, mudança no tamanho da célula também afastou muito do padrão. Agora podemos ver claramente como isso se repete sem parar. Não é aleatório como o ruído de Perlin. É muito matemático e simétrico. Eu amplio um pouco mais. Acho que está claro como isso funciona. Agora, fique à vontade para brincar com ele e fazer seus próprios experimentos. 29. Modo de grade e depuração: Ambos os nós são basicamente uma grade de ângulos. Vamos visualizar essa grade para deixar claro como exatamente ela funciona. Vamos criar um modo de depuração na classe de efeito principal, eu crio um método que chamo, por exemplo, desenhar uma grade. Ele espera contextos como argumento interno. Eu crio um for-loop. Primeiro, vamos desenhar linhas verticais, colunas. Essa propriedade de chamadas de pontos já contém um valor representando o número de colunas na grade. Então, nós o usamos aqui. Toda vez que entramos em uma nova coluna, chamamos start path. Eu queria desenhar uma linha vertical. Vá para o método para definir as coordenadas iniciais x e y da linha. Cada linha começará na posição horizontal dinâmica, tamanho da célula, na largura de uma única célula vezes o número da coluna em que estamos atualmente. Todas as linhas verticais começarão na parte superior a partir da coordenada y zero. linha dois determinará as coordenadas x e y finais de nossas linhas de grade. posição horizontal será novamente tamanho da célula vezes o número da coluna. E eu quero que as linhas terminem totalmente na parte inferior da área da tela. Então, essa altura de ponto. Em seguida, traçamos linhas. Vamos ver o que temos até agora do método de grade de desenho de Colin a partir do método de renderização. Bom. Vemos linhas verticais representando colunas em nosso campo de fluxo. O tamanho da célula é de apenas cinco, então vemos uma linha a cada cinco pixels, eu a altero para 30. Como você pode ver, isso também afetou o zoom no padrão. À medida que o tamanho da célula aumenta, podemos encaixar menos células por linha, o que significa que as espirais criadas pelo seno e cosseno online 85 têm menos tempo para se desenvolver. Tudo isso porque reduzimos o valor do ângulo, passamos para seno e cosseno para números de coluna e linha, menos colunas, menor faixa de valores passados como ângulo para seno e cosseno online 85, que afeta o padrão. Sempre posso compensar isso ajustando essa propriedade de zoom na linha 75. Ok, estamos desenhando linhas verticais. Vamos também desenhar linhas horizontais, as linhas, para completar nossa grade. Novamente, começamos iniciando o caminho começando com as coordenadas x e y de cada linha horizontal que será zero horizontalmente. Portanto, a partir da borda esquerda do Canvas e verticalmente , será o tamanho da célula multiplicado pelo número da linha. O ponto final de cada linha será a borda direita do Canvas. Portanto, essa largura de ponto horizontal, extremidade vertical será novamente tamanho da célula vezes o número da linha. Eu acaricio as linhas. Perfeito. Agora podemos ver a grade completa. Observe atentamente as linhas. Você vê como o valor do ângulo, a direção da linha muda nos pontos à medida que as linhas entram em novas células na grade. Cada célula no campo de fluxo tem um valor de ângulo diferente atribuído a ela, e as linhas seguem esses ângulos para lhes dar a direção do movimento. Esse visual deve ajudar você a entender como os campos de fluxo funcionam preferencialmente. E se você estiver codificando, poderá inspecioná-lo de perto em seu computador e realmente ver o que está acontecendo. Altere o valor do tamanho da célula, dois, um número ainda maior, e o mistério de criar campos de fluxo deve ser resolvido. Eu queria tornar as linhas da grade mais finas, mas não quero que essa alteração afete a largura da linha das linhas fluidas. Por esse motivo, vou agrupar todo esse bloco de código entre segurança e restauração. Esses dois métodos integrados do Canvas garantem que todas as alterações que fizermos um estado permaneçam limitadas a uma área específica. Essas mudanças podem incluir qualquer tipo de configuração como fillStyle, estilo de traçado, largura de linha , opacidade, alfa global, bem como coisas como rotação e escala, que não estamos usando atualmente. Se você quiser saber como usar rotação e escala, pode conferir minha aula sobre frutose. Se eu definir o estilo do traçado para escrever, isso afetará apenas o grau, não as linhas fluidas, nem o sistema de partículas. O método Save cria um ponto seguro, como em um videogame, podemos fazer as alterações que quisermos aqui, por exemplo, largura de linha, apenas 0,3 pixels. Essas alterações afetarão esse código de desenho e, em seguida, serão restauradas. Vamos redefinir todas as alterações feitas aqui até o ponto em que as consideramos seguras. Por isso, quando desenharmos posteriormente as linhas fluidas, o sistema de partículas usando método de desenho na classe de partículas, elas não serão afetadas por esse estilo de traçado e por essa largura de linha. Eu queria manter a grade em nosso projeto, mas quero uma forma de o usuário poder ocultá-la e mostrá-la facilmente. Eu crio uma propriedade de modo de depuração chamada dot d back que será definida como verdadeira inicialmente, da mesma forma que fizemos com Colin aqui. Quando a classe de afeto for instanciada, todo o código dentro do construtor será executado. Na verdade, posso colocar qualquer código que eu quiser aqui, até mesmo um ouvinte de eventos, quando criamos uma instância da classe de efeito usando a nova palavra-chave. Nesse momento, quero um ouvinte de eventos para que o evento key down seja aplicado. Preciso ter certeza de que ainda tenho acesso às propriedades do construtor da classe, especificamente a essa propriedade de depuração de dentro desse ouvinte de eventos. Se você usar uma função de retorno de chamada normal, precisará vinculá-la. Como alternativa, posso usar a função de seta ES6. Essas funções herdam automaticamente o espeto de seu escopo principal. Portanto, mesmo quando esse ouvinte de eventos for executado posteriormente, ele ainda será capaz de lembrar que foi originalmente definido aqui e poderá controlar essa propriedade de depuração de pontos para nós. Se você usar a função de retorno de chamada normal aqui, receberá um erro porque essa palavra-chave se tornará indefinida. Quando o evento key down acontece, console registra esse objeto de evento gerado automaticamente. Decidi chamá-lo por um nome de variável E, mas você pode chamá-lo do que quiser. Se eu abrir esse objeto de evento aqui embaixo, posso ver que ele contém uma propriedade chave nos diz qual tecla foi pressionada. Isso é exatamente o que eu preciso. Se a tecla de ponto E for tripla igual ao operador de comparação com D, defina isso para depurar o valor como seu oposto. Se for falso no momento, defina-o como verdadeiro. Se for verdadeiro no momento, defina-o como falso. Essa é uma linha de código muito útil que nos permite alternar facilmente entre verdadeiro e falso. Eu só quero que esse código seja executado se o modo de depuração for verdadeiro, eu só queria ver esse campo de fluxo degradado quando o modo de depuração estiver ativo. Agora, se você clicar no Canvas e pressionar a letra D no teclado repetidamente, estará ativando e desativando o modo de depuração. Usaremos esse modo de depuração novamente na aula avançada onde mostrarei como rastrear formas e imagens de letras. Agora que as células individuais no campo de fluxo são relativamente grandes, podemos ver claramente que as linhas se quebram e mudam de direção nos limites de cada célula. Porque cada célula contém um valor de ângulo diferente, influenciando o movimento dessas linhas. Sinta-se à vontade para jogar com o código, dê um valor diferente ao tamanho da célula online 70. E então você pode ajustar essa mudança ajustando este Zoom online 75, você pode criar algumas combinações interessantes. Como aqui, onde tenho um padrão bastante interessante que é claramente afetado pelo fato de que células individuais no campo de fluxo têm 50 vezes 50 pixels. Aumentarei gradualmente a curva, a espiral interna do nosso campo de fluxo de cosseno. A beleza da matemática. Você sabia que poderia fazer arte com matemática como essa? 30. Cores randomizadas: Eu abro outra janela do navegador e vou usar o Seletor de cores do Google. Estou procurando algo assim, onde eu possa clicar em qualquer lugar que eu quiser e isso me dê esse valor de cor. Você pode entrar em qualquer faixa de cores que desejar. Eu pego essa cor copiando seu valor hexadecimal. Eu a atribuo como essa propriedade de cor de ponto na classe de partículas. Dentro do método de desenho na classe de partículas, eu disse estilo de traçado para essa cor de ponto. Se todo o campo de fluxo tivesse apenas uma única cor como essa, não faria sentido repetir o estilo de traçado de Colin. Eu o declararia em algum lugar, então ele só é executado uma vez no primeiro carregamento da página para melhorar o desempenho. Mas aqui estou tentando dar às nossas partículas uma faixa de cores aleatória. Eu crio uma matriz, chamo isso de cores de pontos. Eu coloquei esse valor dentro dessa forma. Eu volto ao meu seletor de cores. Comecei com uma cor escura, então vou um pouco mais claro nessa direção, por exemplo, e novamente, copio esse valor hexadecimal. Eu também coloquei essa cor semelhante , mas mais clara , na matriz. Essa cor de ponto será uma cor escolhida aleatoriamente nessa matriz de cores de pontos. Eu posso acessá-los por meio de seus índices. Esse índice de cor de ponto zero é esse. Esse nó com índice de cor 1 é esse. Vamos pegar outra cor e adicioná-la à matriz. Eu escolho mais uma cor, ainda mais clara. Eu escolho mais um. Desta vez, será muito leve. Você pode escolher quantas cores quiser. Não importa quantas cores você adicione a essa matriz. Quero que cada partícula receba aleatoriamente um índice dessa matriz. Como eu faço isso? Obviamente, usando Math.random entre zero e o comprimento dessa matriz de cores de pontos. No entanto, Math.random, ele nos fornece valores de ponto flutuante. Não há índice 1.5 nessa matriz, então eu preciso de números inteiros. Eu embrulho tudo isso em Math.floor. E é assim que você pode atribuir aleatoriamente um valor de uma matriz de valores disponíveis para cada objeto criado por uma classe. Você pode ver que cada linha tem um valor aleatório atribuído e nosso efeito parece mais interessante. Sinta-se à vontade para voltar ao seletor de cores e escolher sua própria gama de cores. Provavelmente seria interessante criar controles deslizantes para esse zoom de pontos para que os usuários possam controlá-lo facilmente. Você pode fazer isso como um desafio no final, se quiser. 31. Design responsivo : Se eu redimensionar a janela do navegador, como em todo projeto do Canvas, elemento canvas não será redimensionado automaticamente. Da mesma forma, estamos aplicando EventListener para o evento keydown aqui no construtor da classe de efeitos colaterais. Também posso criar um ouvinte de eventos para redimensionar o Windows. Estamos dentro de uma classe, então eu não quero tirar a largura e a altura do lado de fora. Então, vamos registrar o console desse objeto de evento gerado automaticamente. Eu removo esse log do console. E eu também removo esse. Portanto, somos um objeto de evento de login do console que foi gerado automaticamente quando redimensionamos a janela do navegador e acionamos o ouvinte de eventos de redimensionamento. Dentro, posso ver o destino do evento, neste caso, o objeto da janela do navegador. E dentro disso, podemos ver o novo atualizado em sua altura e largura. Então, vamos usar apenas esses valores. No console, registre a largura interna do ponto alvo e a altura interna do ponto alvo E. Agora posso redimensionar a janela do navegador e ver a nova largura e altura. Perfeito. Então, quando redimensionamos, eu queria definir a largura e a altura do efeito para esses valores. O problema é que também precisamos redimensionar o próprio elemento da tela. E eu teria que sair da minha classe novamente para pegá-la. Eu queria manter minhas aulas modulares. Eu preciso de uma referência ao elemento canvas dentro da minha classe, eu refatorio esse efeito de código, espero apenas o Canvas como argumento interno, nós o convertemos em uma propriedade de classe. E a partir dessa tela de pontos, agora podemos tirar a largura e a altura desta forma. Tenho 69 anos, agora nos dá acesso ao próprio elemento canvas. Eu fecho o console. Preciso pegar essa variável de tela da linha um e passá-la para afetar o construtor de classe no momento em que criamos uma instância da classe de efeito usando a nova palavra-chave aqui na linha 135. No interior, ele é convertido nesta propriedade de pontos do Canvas. E de sua largura e altura é extraída. Agora, quando o evento de redimensionamento for acionado, chamarei esse método de redimensionamento de pontos, que escreveremos. Próximo. Eu passo a nova largura e altura redimensionar a janela do navegador. Obtemos esses valores desse objeto de evento gerado automaticamente. Vou escrever esse método aqui. Dentro da classe de efeitos. Sabemos que ele espera a nova largura e altura redimensionadas como argumentos. Temos uma referência ao elemento real da tela aqui na linha 69. Então eu pego, e também considero largura e altura. Eu copio essas três linhas e as colo aqui embaixo. Quando redimensionamos a janela do navegador, obtemos uma nova largura e altura. Definimos a largura do elemento da tela para a nova largura. Dissemos altura do elemento de tela até a nova altura. Em seguida, definimos as propriedades de largura e altura do efeito para esses novos valores atualizados. Se eu redimensionar a janela do navegador, parece interessante, mas não tenho certeza se não estamos desperdiçando memória assim. Se eu voltar para um tamanho menor, as linhas devem eventualmente voltar para a área menor disponível. E então, quando eles obtiverem mais espaço, o padrão deve se expandir para um espaço maior. Novamente, acho que a maneira como prefiro fazer isso é chamar o método init. Novamente, depois que a janela foi redimensionada. Não faça o que estou fazendo agora. Não execute esse código porque se eu chamar this.in, ele partir do método de redimensionamento e eu redimensiono a janela do navegador. Algo muito ruim acontece. Estamos inserindo cada vez mais partículas nessa matriz de partículas de pontos, e o efeito diminui consideravelmente. Se eu for até o método init, você pode ver que toda vez que o método init é executado, excluímos a matriz do campo de fluxo e reenchemos com uma nova grade de ângulos. Preciso fazer o mesmo com partículas. Colocamos essas partículas pontuais em uma matriz vazia, excluímos objetos de partículas antigos e criamos um novo conjunto de partículas. Em termos de desempenho, essa não é a melhor solução. Não precisamos de novas partículas. Eu poderia simplesmente ter criado um método de reinicialização em cada partícula. E eu poderia ter redefinido as posições das partículas aqui em vez de excluir todas elas e criar novas para substituí-las. Também poderíamos usar a técnica de agrupamento de objetos aqui se precisarmos aumentar e diminuir o número de partículas, dependendo do tamanho da tela, o que estou fazendo agora funcionar porque estou chamando esse método de inicialização de pontos de dentro do redimensionamento na linha 126. Quando redimensionamos, excluímos o campo de fluxo antigo, degradamos e o substituímos por um novo conjunto de ângulos agora ajustados à nova largura e altura da tela. E também excluímos todas as partículas. E criamos um novo conjunto com posições aleatórias espalhadas pela nova área de tela disponível. Obviamente, para que isso funcione, precisamos ter certeza de chamar isso. partir do método de redimensionamento aqui, presumo que a maioria dos usuários não será redimensionada e a página repetidamente. Portanto, a solução está perfeitamente correta. 32. Experimentando com padrões de campo de fluxo: A forma do campo de fluxo é o que eu chamo de seno e cosseno do padrão de curva em espiral, pouco como um trava-língua para pessoas com formação linguística moderada. Não tenho certeza se essa forma tem um nome oficial. Se isso acontecer, me avise, por favor. É o padrão que você obtém quando usa o aumento nas posições em uma grade bidimensional à medida os valores dos ângulos são passados para seno e cosseno. Nós vemos a fórmula aqui. Essa linha de código que determina a forma do padrão. Podemos jogar com ele de muitas maneiras diferentes e obter resultados muito diferentes. Veja o que acontece se eu substituir a multiplicação pela adição aqui. Ou se eu fizer isso aqui? Ou eu tento isso? Eu ajusto o zoom. Interessante. Também posso ajustar a curva. Você pode simplesmente mudar aleatoriamente os operadores aqui e talvez encontre algo interessante que eu ainda não experimentei. Novamente, é assim que posso diminuir lentamente o padrão. Eu posso aumentar a curva. E devido às mudanças no operador que fizemos ao calcular uma grade angular, agora muda a direção de todo o padrão. Isso parece bom. Talvez eu pudesse usar esse efeito como plano de fundo espacial na próxima aula de desenvolvimento de jogos. Eu poderia até mesmo fazer isso reagir a alguns objetos. Aprenderemos mais sobre isso na próxima parte, onde mostrarei como fazer as linhas fluírem ao redor do texto. Surpreendentemente, fazer menos iguais aqui também mudará o padrão. Isso ficará mais evidente quando eu diminuir o zoom. Acho que isso ocorre porque mudamos em que ponto as células na grade se transformam em uma nova linha. Se eu voltar à multiplicação aqui voltaremos ao padrão espiral usual. Só estou brincando com isso agora. Eu tento mudar no Zoom. Eu mudo a curva. Eu também posso fazer as duas assinaturas aqui. Ou eu posso trocar seno e cosseno. Acho que está claro como isso funciona. Agora, fique à vontade para brincar com ele e fazer seus próprios experimentos. 33. Desenho de texto: Aqui embaixo, no vidro de efeito principal, temos o método init. Ele se divide em uma grade e cria valores de ângulo usando essa fórmula trigonométrica. Eu ainda queria me dividir primeiro na grade. Então, em vez desse algoritmo, quero desenhar texto no Canvas e calcular os valores dos ângulos da grade do campo vetorial a partir daí. Vamos desenhar esse texto primeiro. Para maior clareza, vou colocar esse código em um método separado. Vou chamá-lo de desenhar texto. Eu precisarei acessar o objeto de contexto CTX a partir daqui para poder ver as propriedades do Canvas a partir daqui. No início, vou apenas puxar variável CTX diretamente da linha dois. Vamos refatorar isso em um minuto. A partir daí, eu acesso a propriedade da fonte e a defino para 500 pixels de impacto. Eu quero letras grandes em negrito. Em seguida, chamo o método filtText embutido, que espera pelo menos três argumentos, o texto a ser desenhado e as coordenadas x e y onde desenhá-lo. O texto que eu quero desenhar é o JS, porque estamos aprendendo sobre JavaScript hoje. coordenada horizontal será essa largura de ponto, a largura do Canvas vezes 0,5. No meio da tela horizontalmente, coordenada y vertical será essa altura de ponto vezes 0,5, o meio da tela verticalmente. Como você pode ver, estou puxando a variável CTX da linha para diretamente dentro da minha classe. Quero seguir as boas práticas e manter nossas aulas independentes. Então, vou refatorar isso. Eu precisarei acessar o CTX a partir do método de texto Draw, bem como do método init, porque é daí que o método de desenho de texto será chamado. Também preciso acessar esse mesmo contexto a partir do método draw a grid. Como precisamos do CTX em muitos lugares diferentes em toda a classe de efeitos, escolherei a seguinte solução. Temos ctx aqui na linha dois. Vou me certificar de afetar o construtor de classe esperado como argumento. E por dentro, vou convertê-lo em uma propriedade de classe chamada contexto de pontos. Assim. Usaremos esse contexto de pontos aqui e aqui dentro do método de desenho de texto. Além disso, dentro da taxa de medicamentos, isso não será mais esperado como um argumento vindo de fora. Em vez disso, em todos esses lugares, usarei essa propriedade de classe de contexto de pontos que acabamos de criar. Também usamos contexto dentro da renderização. Não esperará mais o contexto como argumento. Também removerei o argumento de contexto passado para o método de desenho em partículas e aqui passado para desenhar uma grade. Acho que cometi alguns erros aqui. Tenha paciência comigo um segundo, por favor. Na verdade, tenho que aprovar esse contexto de lei para desenhar um método em partículas como essa. Ok, eu executo o código, recebo um erro. Eu abro o construtor da classe de efeitos do console do navegador expect CTX e o converto nessa propriedade de contextos de pontos. Preciso ter certeza de passar CTX aqui na linha cento e 51 ao criar uma instância dessa classe. Além disso, não preciso mais passar CTX para o método de renderização. Aqui. Eu pego o método de desenho de texto e o chamo de dentro da renderização assim. Quando passamos as coordenadas x e y para o método filtText, essas coordenadas definem o ponto de ancoragem desse texto em que o texto é desenhado em relação a esse ponto de ancoragem, dependendo do valor dos textos, da linha e das propriedades do Canvas da linha de base do texto. O alinhamento de texto controla o alinhamento horizontal. Colocamos o ponto de ancoragem do texto no meio da cannabis. Então veja o que acontece quando eu coloco a linha de texto no centro. Também posso usar a propriedade da linha de base do texto para alinhar o texto verticalmente em relação às coordenadas do ponto de ancoragem. Eu o coloquei no meio. Mais uma vez. Quando você desenha texto sobre cannabis, os valores que você passa para coordenadas x e y do FiltText definem o ponto de ancoragem em que o texto fica em relação a esse ponto de ancoragem dependem dos valores que você atribui às propriedades de texto, linha e linha de base do texto. Por padrão, o texto é alinhado à esquerda horizontalmente e a linha de base alfabética verticalmente. Nós os colocamos no centro, no meio para obter um texto centralizado como este. É muito importante entender isso se você precisar trabalhar com texto em uma tela HTML, definirei a depuração como verdadeira para ativar o modo de depuração Quero que esse texto fique visível no modo de depuração. Oh, eu tenho um erro. O console está me dizendo que está aqui. Eu preciso usar esse contexto de pontos aqui também para desenhar minha grade. Provavelmente já percebi isso antes. Então, quando estamos no modo de depuração, quero ver o campo vetorial se degradar. E eu quero que você veja essas grandes letras brancas que determinarão a forma do campo de fluxo. Ser capaz de mostrar e ocultar esse texto facilmente pressionando a letra D no teclado, ao entrar no modo de depuração, facilitará a compreensão e a modificação do efeito. Renderização interna. Eu digo que se essa é a depuração é verdadeira, só então desenhe uma grade e desenhe o texto. Agora, você pode pressionar a letra D repetidamente para ativar e desativar o modo de depuração. 34. Entendendo os dados dos pixels: Dentro do método init, eu quero desenhar para x neste ponto. Lembre-se de que o método init será executado apenas uma vez no primeiro carregamento da página e criará um campo vetorial e um sistema de partículas para nós. Depois de desenhar essas grandes letras brancas no Canvas, quero que você escaneie o Canvas em busca de dados em pixels. Meu objetivo final é saber quais células na grade têm formas de letras atrasadas e quais células da grade contêm apenas o fundo preto vazio. Eu faço isso escaneando cannabis em busca de dados de pixels depois de desenhar esse texto nela. E vou analisar esses dados em pixels e mapeá-los na grade. Vou chamar o método get ImageData integrado. Esse método retorna um objeto de dados de imagem gerado automaticamente representando os dados de pixel subjacentes uma porção específica da cannabis. Ele espera quatro argumentos para especificar qual porção de cannabis queremos analisar. Eu quero pixelizar dados de todo o elemento da tela. Então, da coordenada zero a essa largura de ponto, essa altura do ponto. Em outras palavras, obtenha ImageData. Vou escanear uma parte específica da cannabis em busca de dados de pixels, podemos extrair cores e coordenadas de cada pixel dela. Para fazer isso, preciso entender como os dados nesse objeto de dados de imagem gerado automaticamente são organizados? Vou atribuir isso a uma variável constante que chamo, por exemplo , pixels, e nosso console a registrará. Eu posso ver o objeto de dados da imagem aqui no console. Eu o abro e posso ver que tem largura e a altura da área digitalizada. Isso é importante. Precisamos conhecer esses valores para que possamos extrair as coordenadas x e y de cada pixel a partir disso. Se soubermos a largura, quantos pixels temos, cada linha de dados, saberemos depois de quantos pixels essa matriz se divide em outra linha. A tela é digitalizada. E na mesma ordem, criamos nossa grade angular linha por linha, de cima para baixo, indo da esquerda para a direita em cada linha. Se eu abrir essa matriz de dados, é aqui que todas as informações do pixel são armazenadas. Na verdade, é muito simples. Ele contém apenas uma longa sequência de números inteiros. console do meu navegador divide essa matriz extremamente longa em blocos, mas na verdade é uma longa linha de números. Como isso se traduz em pixels? Eu posso ver que esse é um tipo especial de matriz chamada matriz fixada UI e T8. Ele só pode conter números inteiros de oito bits sem sinal fixados para organizar de 0 a 255. Sabemos pela declaração de cores RGBA em CSS que cada cor pode ser representada por uma combinação de vermelho, verde e azul. Cada cor tem um valor de 0 a 255. E combinações diferentes delas nos permitem criar qualquer cor na declaração de cores CSS RGBA. O valor da opacidade Alfa é 0-1. Aqui nessa matriz de pixels, alfa também é representado por um valor de 0 a 255. Precisamos lembrar que a matriz de dados de pixels é uma linha extremamente longa de números em cada quatro valores representa vermelho, verde, azul e Alfa sobre um pixel, um único pixel. Então esse é o pixel 1. Os próximos quatro valores, nosso pixel dois e assim por diante. Eu posso ver que a largura da área digitalizada é 528 pixels e a altura é de 464 pixels. 528 vezes 464 é um total de 244.992 pixels digitalizados. E sabemos que cada um desses pixels é representado por quatro valores em pixels. Matriz. Valor para vermelho, verde, azul e Alfa. 244.992 vezes quatro é 979.968. Aqui podemos ver que a matriz de dados de pixels tem exatamente 979.968 elementos. Então, isso se verifica. Se eu olhar em algum lugar no meio da matriz, poderei encontrar esses pixels brancos que compõem as formas das letras. Aqui eu posso ver que temos 55 a 55 a 55, que é branco, e 2554 alfa totalmente visível. Sabemos que esses quatro pixels com índice 533.600 na matriz de dados de pixels representam pixels em algum lugar nessa área branca. Se eu mudar o estilo de preenchimento também, certo? Eu abri a matriz. Na maioria das vezes, vejo que pixels pretos são zeros, zeros 00 de opacidade porque o fundo da nossa tela é transparente. Aqui eu posso ver aqueles pixels vermelhos de 55 lidos de zero, verdes, zero de azul a 55 Alpha. Esses valores representam um pixel vermelho totalmente visível, em algum lugar na área vermelha, sabemos que esses pixels são o texto desenhado no Canvas. 35. Tratando dados de pixels: Ok, então o método init executará todos os que estão no primeiro carregamento da página e, por dentro, estamos tentando criar uma grade de ângulos, um campo vetorial. Desenhamos texto e nos digitalizamos com esse texto desenhado nele com o método get ImageData integrado. Agora, estamos mantendo todos os valores de pixels dentro dessa variável de pixels. Vou comentar este código que calculou ângulos espirais para cada célula na grade usando nossa fórmula especial de seno e cosseno. Em vez disso, farei a forma do texto das letras para determinar os ângulos mantidos em cada célula do campo vetorial. Para fazer isso, precisamos usar o nested for loops. Novamente, o loop externo para percorrerá o Canvas linha por linha, saltando pelo tamanho da célula. Cada vez que inserimos uma nova linha, definimos o tamanho da célula como 20 pixels. Aqui na linha 75, posso mostrar e ocultar essa grade feita de 20 vezes 20 células pressionando a letra D no meu teclado. No interior, o loop interno percorrerá cada linha horizontalmente da esquerda para a direita. Também pulando de célula para célula pelo valor do tamanho da célula. Espero que agora entendamos como esses dois, aninhados , percorrem a tela, linha por linha, de cima para baixo. Toda vez que inserimos uma nova célula na grade, precisamos calcular um índice. Já calculamos o índice aqui na linha 40. Essa fórmula nos ajuda a converter as coordenadas x e y em um único valor representando o índice em uma matriz. À medida que percorremos a grade célula por célula, linha por linha, quero combinar a posição da célula com um índice correspondente a essas coordenadas na matriz de pixels para saber quais dados de pixel foram digitalizados para essa célula em particular. Uma correspondência nas coordenadas x e y da célula. Atualmente, estou trocando esses loops aninhados para um índice específico na matriz de pixels para extrair dados de pixels para essa área de tela. Novamente, essa é a fórmula em que multiplicamos o número da linha pela largura. Então, obtemos pixels por linha mais x, que representa quantos pixels estamos atualmente em uma nova linha. Desta vez, estamos tentando combinar o índice na matriz de dados de pixels. Sabemos que cada partícula é representada por quatro elementos, quatro inteiros, 0-255, representados em vermelho, verde, azul e alfa. Então, para obter o índice correto, eu multiplico isso por quatro. Agora eu conheço o índice na matriz de pixels que corresponde às coordenadas x e y dessa célula específica no campo vetorial, o grau. Eu quero a cor com a qual começo, certo? Vermelho será a matriz de pixels nesse índice. O verde será o único índice que virá depois. Então, índice de pixels mais um. Azul é índice mais dois. Então temos Alfa, índice mais três. Em seguida, obtemos o valor vermelho do próximo pixel, verde, azul, alfa e assim por diante e assim por diante. Portanto, temos vermelho, verde e azul de cada pixel. A combinação desses valores nos dará a cor do pixel subjacente. No momento, todos os pixels do texto estão vermelhos, mas vamos mudar isso em breve. 36. Convertendo cores em ângulos: Meu objetivo agora é fazer com que a cor das letras afete a direção do fluxo, o ângulo na grade do campo vetorial, por exemplo, pixels vermelhos empurram o fluxo para a direita. A cor azul flui para baixo, cor verde flui para a esquerda, por exemplo, e todos os valores de cor intermediários nos dão um ângulo em algum lugar entre essas direções. Há muitas maneiras de converter cores em ângulos, e podemos obter muitos efeitos diferentes aqui. A maneira mais fácil seria converter de alguma forma os três valores de vermelho, verde e azul em um único número. Posso, por exemplo gerar um valor em escala de cinza a partir dessa calibração de cores RGB de forma que, quando todas as três cores de vermelho, verde e azul forem iguais, a cor resultante seja um tom de cinza. A cor está em algum lugar no espectro da escala de cinza, sem uma tendência para a visualização em vermelho, verde ou azul. Podemos converter para tons de cinza obtendo a média dos três, vermelho mais verde mais azul dividida por três. Agora, eu poderia criar um efeito de escala de cinza a partir disso pegando esse valor médio e aplicando-o novamente em vermelho, verde e azul. Mas, na verdade, eu só queria pegar esse valor médio único e convertê-lo em um valor angular. Temos uma gama de cores em tons de cinza que vai de 0 a 255. E eu quero mapear esses valores em dois ângulos, 0-6, 0,28 rad, 6,28 rad, convertidos em 360 graus, um círculo completo. Portanto, as cores podem fluir em qualquer direção dependendo do valor da escala de cinza dessa área, já que estamos operando apenas em valores positivos. Portanto, a fórmula é muito simples. Considere a razão entre a escala de cinza atual dessa célula no campo vetorial e o valor máximo. E aplique essa proporção a esse valor de ângulo. Digamos que se a escala de cinza for 127,5, isso é metade de 50% entre o valor mínimo de zero e o valor máximo de 250. 527 pontos 5/255 é 0,5. Temos a razão, e agora eu a multiplico pela faixa angular máxima de 6,28 rad, o que nos dará metade desse valor, 3,14. 3,14 é um semicírculo pi. A propósito, se a escala de cinza for, por exemplo , 63,75, 63,75 dividida pelo valor máximo de 255 nos dá uma proporção de 0,25, 25 por cento em relação ao valor máximo, um quarto. Aplicamos a mesma proporção ao valor máximo do ângulo 0,25 vezes 6,28 nos dá 1,57 rad meio a um quarto de círculo. Basicamente, estou considerando a proporção, a relação entre o valor atual da escala de cinza e o valor máximo de cor possível de 255. E estou aplicando essa proporção à faixa de ângulo 0-6, 0,28 rad. Como usamos uma escala de cinza como essa, o fluxo resultante será influenciado pela claridade ou escuridão das cores no espectro da escala de cinza. Eu vou te mostrar o que quero dizer quando começarmos a animação. Quero limitar quantos pontos decimais obtemos aqui pois não há necessidade de calcular valores de ângulos minúsculos. Dois pontos decimais estão bem. Eu coloquei toda a expressão entre colchetes, para que eu possa chamar o JavaScript embutido para um método fixo nela. Eu passo para, eu quero apenas dois pontos decimais. Ok, então, à medida que o método init é executado, definimos o campo de fluxo como uma matriz vazia. Aqui embaixo, vou preencher a matriz com uma grade de valores angulares embutida no método de push de matriz. E empurraremos um objeto com a propriedade x definida como coordenada x, coordenada horizontal do interno para loop à medida que saltamos pelo tamanho da célula em cada linha de compra e venda de células, y será o índice y do externo para o loop à medida que saltamos pelo valor do tamanho da célula sobre cannabis, linha por linha, de cima para baixo. O valor do ângulo de cor é essa faixa de cores em tons de cinza convertida em um valor de ângulo em radianos, o que garantirá que as partículas fluam em uma direção diferente em cores diferentes. No console, podemos ver esse objeto de dados de imagem. Na verdade, não quero que ele aponte para o objeto inteiro, mas apenas para a matriz de pixels, que é mantida aqui dentro da propriedade data. Os pixels serão o objeto ImageData retornado pelo método embutido get ImageData dot data. Estamos apontando diretamente para essa matriz agora. Agora vemos isso no console aqui. matriz de campos de fluxo agora contém objetos com propriedades x, y e ângulo de cor para cada célula na grade do campo vetorial. Precisamos ter certeza de que consideramos essa alteração quando a atualização das posições das partículas aparece dentro do método de atualização na classe de partículas. Aqui, estamos retirando o valor do ângulo da matriz do campo de fluxo dependente da posição atual X e Y das partículas no Canvas. Agora, há um objeto com três propriedades em cada índice, então eu preciso acessar sua propriedade de ângulo de cor aqui. Assim, ótimo, algo está acontecendo. Temos dois problemas para resolver. Eu só quero executar esse bloco de código que corresponde à posição da partícula com um objeto representando uma célula no campo de fluxo. Se houver um objeto nesse índice no ângulo de cor puxado por Dan, isso resolverá o problema de as partículas se moverem para fora dos limites do Canvas entre as recitações. O segundo problema, se você estiver codificando, poderá diminuir o zoom e ver que já estamos desenhando em um campo de fluxo em forma de letras JS, mas por algum motivo ele está inclinado para a direita. Por que isso? Vou diminuir a fonte para que possamos ver que temos a forma, mas por que ela está distorcida assim? Estou tornando a célula menor. Agora podemos ver claramente o campo de fluxo tem o formato das letras JS, mas está distorcido de uma forma estranha. Na verdade, demorei alguns minutos para perceber o que está acontecendo, mas vamos avançar para a solução. Se você sabe por que está fazendo isso antes de eu revelar, pause o vídeo e digite-o nos comentários. No momento, você vê aqui que estamos definindo largura e a altura da tela para a largura e altura atuais da janela do navegador. O problema é que, quando criamos o campo de fluxo, se o valor do tamanho da célula estiver na classe de efeito principal, a largura e a altura de cada célula na grade não são um número pelo qual a largura da tela possa ser dividida. Sem nenhum resto, obteremos alguns pixels restantes quando quebrarmos a linha enquanto digitalizamos Canvas linha por linha, de cima para baixo. À medida que descemos linha por linha, os pixels restantes no final de cada linha se acumulam e o campo de fluxo se degrada. E o campo de fluxo se degrada. O número de elementos lá não corresponde exatamente ao número de células que podemos colocar no Canvas. Assim, as linhas são empurradas cada vez mais para a direita. Há várias maneiras de resolver isso. Só precisamos garantir que a largura da tela seja divisível pelo tamanho da célula, sem nenhum resto, sem nenhum valor restante. Vou resolver isso definindo a largura da tela para um tamanho específico. Mas você também pode usar uma fórmula dinâmica aqui usando o operador restante. Se você quiser mantê-lo em tela cheia, se quiser manter a funcionalidade responsiva. Eu disse largura da tela de 600 pixels. E como o tamanho da célula na linha 75 está definido como 20 pixels, 600 é divisível por 20 sem nenhum resto, então estamos obtendo a forma correta. Também definirei a altura da tela para 600 pixels, ou talvez 500 vezes 500. Quando eu redimensiono o Canvas, nosso método de redimensionamento do cliente é acionado e quebra a forma novamente, pois permite que a largura da tela seja algo que não é diretamente divisível pelo tamanho da célula sem um resto diretamente divisível pelo tamanho da célula sem um resto. Posso garantir que ele pesquise apenas tipo de tamanho se a nova largura for divisível pelo tamanho da célula. Ou eu posso apenas comentar isso por enquanto, aqui na linha 92. E como o Canvas tem 500 vezes 500 pixels, quero que ele fique centralizado exatamente no meio da página. Eu posso fazer isso com CSS. Ele já está posicionado como absoluto, então eu dou a ele um top 50 por cento, deixo 50 por cento e transformo translate -50% -50 por cento. Obviamente, você pode posicioná-lo de uma maneira diferente, dependendo de onde quiser. Agora vou definir o plano de fundo do elemento do corpo como preto. Acho que isso parece bom por enquanto. Eu aumento o tamanho da fonte. 450 talvez. Sim, estamos convertendo cores em um ângulo. Portanto, veja para onde as partículas estão fluindo quando o texto está correto. E veja o que acontece com sua direção de movimento. Quando eu mudo a cor para verde. Na verdade, o ângulo azul é semelhante a lê-lo porque não estamos espalhando a faixa de cores em si, mas primeiro a convertemos em escala de cinza e depois a convertemos em ângulo. Parece que azul e vermelho têm um valor de escala de cinza muito semelhante. Você verá a maior diferença nos ângulos ao usar cores claras ou escuras. Cores que estão distantes no espectro da escala de cinza. Castanho. Vamos tentar algo muito mais claro, amarelo. Podemos ver claramente que a direção do fluxo é influenciada pela cor, pela cor do texto, perfeita. 37. Fluxo e gradientes: Eu poderia deixá-lo aqui, mas eu estava brincando com ele e descobri mais coisas muito legais que quero compartilhar com você. Essa é sempre minha parte favorita em que temos toda a lógica estabelecida. O efeito está funcionando e eu posso experimentar. Sabemos que as diferentes cores empurram o fluxo de partículas em direções diferentes. Então, vamos ver o que acontece quando o preenchimento do texto não é apenas uma cor, mas um gradiente que passa de cor para cor. Eu me pergunto como isso vai parecer. Uma variável personalizada chamada de gradiente de gradiente, e eu chamo de método embutido de criação de gradiente linear do Canvas. Ele espera quatro argumentos, x e y do ponto inicial e x e y do ponto final. O gradiente será desenhado ao longo de uma linha entre esses dois pontos. Quero um gradiente a partir das coordenadas do canto superior esquerdo, zero em direção ao canto inferior direito coordenadas, largura do efeito e altura do efeito, que são iguais à largura e altura da tela. Agora posso pegar esse gradiente de uma variável e chamar o método embutido de adição de interrupção de cor a partir dela. No offset 0.2, a cor será branca, por exemplo, 0.8 offset. Eu tento o full blue. Agora eu posso simplesmente definir fillStyle para essa variável de gradiente único. Incrível, isso é muito legal, como a forma como o fluxo se curva à medida que passamos do azul para o branco. Agora que entendemos isso, podemos experimentar diferentes faixas de cores e gradientes diferentes. Eu adiciono outra parada de cor no ponto zero para a cor amarela. 0.6 será, por exemplo, verde. Eu posso simplesmente brincar com os valores das cores para ver o fluxo que obtenho. É interessante como a direção do fluxo muda conforme a transição das cores segue o gradiente. Esqueci de mencionar um recurso importante dos métodos Canvas integrados ao FiltText e ao stroke text podemos passar a eles quinto argumento opcional para definir a largura máxima do texto. Eu direi que a largura máxima do texto é o peso da tela. Agora, se o texto for mais longo, ele será compactado para caber na área. Se eu quiser algumas margens, posso dizer que essa largura de ponto vezes 0,8. E o texto ocupará o máximo de 80 por cento do Canvas. Serão necessários 80 por cento se dermos mais espaço definindo a largura da tela para um valor maior. Eu volto ao tamanho da tela 500 vezes 500 pixels. Eu mudei a palavra para fluir. Podemos mudar a fonte para Helvetica, por exemplo, voltar ao impacto. E os textos serão JS. Eu quero que ele flua para se curvar mais para a direita. Então, eu jogo com os valores das cores para fazer que o gradiente influencie a direção do campo de fluxo. Isso parece bom. Eu copio esse bloco de código e também renomeio todos esses gradientes. E eu uso isso como FillStyle online 112th. Eu jogo com os valores novamente para ver o que acontece. Eu sei aproximadamente em qual direção cada cor flui, mas é principalmente tentativa e erro. Isso parece interessante. Eu crio um gradiente três copiando esse bloco de código e usando-o como fillStyle online cento e 18. Desta vez, será um gradiente radial, então precisamos passar seis argumentos, x e y do ponto central do círculo interno. É raio. Então, eu queria que o círculo interno começasse exatamente no meio da tela horizontal e verticalmente. E o raio será de dez pixels. A borda externa do círculo de gradiente radial estará novamente no meio do Canvas e o raio será a largura da área de trabalho. Interessante. Eu ajusto as cores para ver qual forma eu tenho. Você pode ver como o gradiente radial afeta o fluxo de uma maneira diferente. Eu gosto muito desse. Vou manter todos os três gradientes que defini para poder trocá-los mais tarde, se quiser. 38. Dicas, truques e experimentos: Quando os ângulos mudam de direção, é uma curva acentuada. Pode funcionar para você, mas talvez queiramos que as linhas girem mais gradualmente quando o ângulo no campo vetorial muda. Estamos mantendo o valor do ângulo atual para cada partícula aqui na classe de partículas principal. Estamos alterando esse valor dentro do método de atualização para corresponder ao valor do ângulo da grade no campo de fluxo. Vou criar outra propriedade aqui chamada novo ângulo. E vou verificar a diferença entre o ângulo atual e o novo ângulo. E em vez de mudar para esse novo ângulo instantaneamente, quando as partículas entrarem em uma nova célula na grade do campo de fluxo, nós apenas empurraremos as partículas em direção esse novo ângulo com uma certa fração de sua diferença. Ou para reduzir os cálculos necessários, em vez de calcular a fração da diferença entre o ângulo existente e o novo ângulo, posso simplesmente definir um valor chamado caractere angular. Será um valor pequeno em radianos. Aqui embaixo no método de atualização, eu disse novo ângulo dois, um ângulo armazenado na célula do campo vetorial. E eu digo que se o ângulo atual da partícula for mais do que um novo ângulo, reduza o valor do ângulo da partícula pelo valor do caractere angular que definimos, mova o ângulo existente um passo mais perto do novo ângulo, eu escolho fazer isso dessa forma para economizar desempenho. Você também pode dizer que altere o valor do ângulo um décimo da diferença entre o ângulo e o novo ângulo, o que fornecerá curvas mais graduais em detrimento do desempenho pois são necessários mais cálculos. Caso contrário, se o ângulo for menor que o ângulo u, aumente o valor do ângulo pelo caractere do ângulo. Mais uma vez em outro lugar, definimos o ângulo para o novo ângulo. Agora você pode ver que as curvas fechadas sumiram e estamos apenas empurrando suavemente as partículas em direção a determinados valores angulares. Eu ajusto o valor do ângulo dos caracteres para pressioná-los um pouco mais. Ou podemos fazer um valor aleatório aqui entre pequena faixa para que cada partícula se curve de forma diferente. Eu posso ajustar o comprimento máximo. Eu posso mudar o modificador de velocidade. Temos toda a lógica estabelecida. Se quiser, você pode brincar com ele para ver quais variações desse efeito você pode criar. Portanto, esta é minha maneira básica de desempenho eficiente, fazer com que as partículas mudem de direção mais gradualmente à medida que fluem pela grade de células no campo de fluxo. Eu também gostaria de poder controlar quantas partículas fluem dentro das formas das letras e quantas fluem na área externa das letras. Agora, é completamente aleatório, mas não precisa ser quando as partículas se reiniciam. Eu queria verificar se ele está sendo redefinido dentro ou fora das formas das letras, em algum lugar na área transparente ao redor da letra. Se estiver fora das letras, eu queria tentar novamente. Eu terei uma variável chamada tentativa. Começará do zero. No início. Eu terei uma bandeira chamada sucesso de reinicialização. Inicialmente, será falso. Quando as partículas se reiniciarem dentro das formas das letras, mudaremos isso para verdadeiro. Vou fazer um loop longo. Quando as partículas se reiniciaram, eu queria tentar cinco vezes. Ele fará cinco tentativas de escolher aleatoriamente uma posição em algum lugar no Canvas para tentar redefinir as formas das letras. Desde que as tentativas sejam menores que cinco e desde que o sucesso da reinicialização seja falso, criarei um índice de teste. Será uma célula aleatória em algum lugar na matriz do campo de fluxo. Eu verifico se esse índice de teste tem alfa maior que zero, o que significaria que é a célula no campo de fluxo que tem alguma cor visível em seus dados de pixel, que significaria que é uma das letras. Como alternativa, será transparente, o que significa que é o fundo vazio ao redor das letras. Se tiver Alfa maior que zero, significa que encontramos uma das células das letras. Então, definimos as posições x e y da partícula para as posições x e y da célula no campo de fluxo. A grade. Aqui embaixo, posso ver que células cheias de fluido objetos dentro da matriz do campo de fluxo contêm valores de ângulo de cor, x e y. Então, esses X e Y virão daí. Eu disse que essas coordenadas x e y eram o primeiro ponto no caminho adicionando-as à matriz do histórico. E eu redefino o cronômetro para os termos dois do comprimento máximo. Também definirei o sucesso da reinicialização como verdadeiro. É importante ressaltar que preciso ter certeza de que toda vez que tentarmos fazer isso, aumentemos a tentativa em um para que, quando chegarmos a cinco, esse loop inteiro, e não queiramos criar um loop inteiro sem fim. Isso continuará somente enquanto essas duas condições forem verdadeiras. Portanto, somente quando as tentativas são menores que cinco e, ao mesmo tempo, desde que o sucesso da reinicialização seja falso. Se eu executar o código, ele não será redefinido de jeito nenhum. Isso indica que essa condição na linha 78 está sempre retornando falsa. É porque não estamos inserindo esse valor Alfa em nossos objetos celulares de campo de fluxo. Eu mudei as tentativas aqui para 50. Então, aqui embaixo, estou calculando o alfa online 160. Preciso ter certeza de que o valor realmente acabe dentro da matriz do campo de fluxo. Assim. As linhas perfeitas estão sendo redefinidas dentro das letras. Eu disse no máximo, tente voltar para quatro após o término do loop inteiro. Se depois de tentar reiniciar quatro vezes, ainda não encontrarmos uma célula com alfa maior que zero e reiniciarmos, o sucesso ainda é falso. Vamos reiniciar as coordenadas x e y dessa partícula em algum lugar aleatoriamente ao redor da tela. Ainda não está redefinindo partículas fora do formato das letras. Mesmo quando eu diminuo para apenas duas tentativas. Que tal apenas uma tentativa? Eu vou descobrir isso. Só me dê um segundo, certo? Eu tenho que colocar essas novas posições dentro da matriz histórica. E o mais importante, tenho que redefinir o cronômetro para comprimento máximo vezes dois para que as partículas se animem. Bom. Agora, quando as partículas são reiniciadas, esse código tentará redefinir algumas vezes as partículas dentro das formas das letras. E se não encontrar a célula em uma certa quantidade de tentativas, ela simplesmente reiniciará a partícula em algum lugar aleatoriamente ao redor do Canvas. Podemos ajustar quantas partículas queremos redefinir dentro e fora das formas das letras alterando o número de tentativas na linha 75. Na última tentativa, menos provável é que as partículas encontrem as formas das letras a tempo. Então, eles podem reiniciar do lado de fora. Posso aumentar o número de partículas e aumentar o tamanho da célula. Podemos ver que a maioria das partículas agora é redefinida em formas de letras, mas ocasionalmente fazemos uma reinicialização em outro lugar, algum lugar externo. Você pode ajustar o número de partículas e tamanho da célula de acordo com o que quiser e o que seu computador pode manipular aqui. Eu posso remover esse código. Acho que todos agora entendemos como esses valores afetam a animação. Talvez 2000 partículas. E se eu adicionar a cor branca à matriz de cores para alguns destaques? Interessante, eu o removo novamente. Eu tento o gradiente um para mudar a direção do campo de fluxo. Gradiente também. Acho que meu favorito é o gradiente três. Qual deles você prefere? Eu aumento o comprimento máximo, o que afeta o desempenho. Linhas mais longas exigem mais poder computacional para serem desenhadas. Então, criamos uma grade, desenhamos texto no Canvas. Analisamos esse tipo de nós com textos desenhados nele. Para dados de pixels, alternamos esses dados em pixels em uma grade para extrair valores de cor e coordenadas de cada pixel. E convertemos esses resultados em cores em ângulos. A partir dessas informações, criamos um campo de fluxo, uma grade de ângulos, em que a direção dos ângulos é influenciada pelo texto que foi desenhado no Canvas. Eu posso remover esse bloco de código. Em seguida, criamos um sistema de partículas aqui. Talvez eu quisesse que as partículas começassem a fluir a partir das formas das letras, mesmo no primeiro carregamento da página. Então, acionarei manualmente método de reinicialização em cada partícula à medida que as crio, o que as forçará a fazer algumas tentativas de encontrar células no campo de fluxo que contenham alguns valores de cor, células que estão acima das formas das letras. Eu mudei o texto para fluir. Você pode ver que isso mexe com o gradiente radial, o que é esperado. Aumente a largura da tela para 1500 pixels. Eu posso criar a largura máxima do texto aqui embaixo. Posso usar gradientes para mudar a direção do fluxo. Isso parece interessante. Que tal o gradiente um? Você provavelmente percebeu que isso funcionaria em imagens, assim como eu estou apenas usando get ImageData para obter formas de letras que foram desenhadas no Canvas. Você quer aprender como usar isso em imagens? Eu vou te mostrar exatamente como fazer isso na próxima parte. Espero que você esteja se divertindo. 39. Campos de fluxo de imagem explicados: Então, construímos um campo de fluxo de texto e fizemos experiências com ele. Eu coloquei o texto de volta em js maiúsculo para que ele caiba na tela e possamos ver tudo. Você pode baixar as imagens que usarei na seção de recursos abaixo, ou você pode usar as suas próprias. Vou usar imagens pequenas, 200.200 pixels com um tamanho em torno de 10 kb. O tamanho das imagens é importante para o desempenho. Então, se você estiver usando suas próprias imagens, pense nisso e otimize as imagens antes de usá-las para este projeto Se você quiser que sua animação funcione sem problemas, esse efeito fica ótimo com algumas imagens específicas. Pela minha experiência, o melhor resultado é com formas simples com cores gradientes, pois isso fará com que o fluxo se curve bem. Em index.HTML, eu crio um elemento IMG com um ID de estrela e a fonte apontará para essa imagem. Se você se lembra da parte anterior, o truque era desenhar texto no Canvas e depois analisar esses dados de pixel e criar um campo vetorial, uma grade de ângulos a partir dessa forma. Eu quero fazer a mesma coisa aqui com uma imagem. Agora, eu queria desenhar essa imagem no Canvas e depois quero digitalizar esse tipo de nós com essa imagem desenhada nela. O problema é que existem algumas limitações nesse compartilhamento de recursos de origem cruzada. É uma medida de segurança que não nos permite desenhar nenhuma imagem aleatória no Canvas e depois digitalizar esse Canvas em busca de dados de pixels. Se a imagem não for da mesma origem, esse tipo de nós é considerado contaminado por dados de origem cruzada. E seu código terminará com um erro de console ao desenhar uma imagem no Canvas e digitalizá-la com get ImageData, essa imagem precisa ser considerada a mesma origem. Se você estiver executando seu código a partir de um servidor, a fonte da imagem aqui aponta para uma imagem armazenada no mesmo endereço do servidor. Então funcionará. Quero que essa base de código seja flexível e funcione facilmente localmente. Não quero falar sobre a configuração de um servidor local agora. Portanto, uma possível solução é converter a própria imagem em uma sequência de dados chamada base 64. Para fazer isso, podemos usar o URL de dados construído no método JavaScript, ou há muitos sites que farão isso por nós em segundos. Resumindo, para evitar problemas de compartilhamento de recursos de origem cruzada, estou convertendo o próprio arquivo de imagem em uma string de dados e, em seguida, usarei essa sequência de dados como fonte de imagem. Eu faço isso pelo Google e P e G, dois de base 64. Observe que a imagem não precisa ser PNG. Ele também funcionará com outros formatos. Eu escolherei, por exemplo, este site do site online PNG tools.com. Mas os outros sites funcionarão de forma semelhante. Eu arrasto e solto a imagem que eu quero converter do meu computador para esse campo. E ele converterá instantaneamente todo o arquivo de imagem em uma linha de código muito longa. Use a menor imagem possível em termos de largura e altura, além de kilobytes. Caso contrário, esse código será muito longo e causará problemas de desempenho quando o animarmos em um minuto. Idealmente, use as imagens e forneça. E depois de ter um efeito funcional, você pode trocar por um arquivo de imagem diferente. Essa sequência de dados de base 64 precisa começar como essa imagem de dois pontos de dados. Se não for para você, clique nessa caixa de seleção para convertê-la em um formato específico de que precisamos. Eu copio essa linha de código extremamente longa e a colo como um atributo de origem aqui. No Visual Studio Code, posso clicar em Exibir e agrupar palavras para tornar o arquivo de código mais gerenciável. Como você pode ver, estamos desenhando essa imagem em estrela, mas nunca usamos o arquivo de imagem real. Essa longa sequência de código substitui completamente o próprio arquivo de imagem. E como todo esse código está dentro do nosso arquivo HTML de índice, ele é considerado a mesma origem em todas as circunstâncias. E, portanto, podemos fazer operações avançadas de pixels nele com tela HTML sem acionar um erro contaminado do Canvas. Deixe-me te mostrar. É fácil fazer isso funcionar agora, eu realmente não quero desenhar o elemento da imagem em si, então pego seu id e o escondo com CSS. Em vez disso, eu quero desenhá-lo no Canvas, onde o JavaScript, eu vou para o efeito principal da classe e crio uma nova propriedade chamada essa imagem de pontos. Eu apontei essa variável para aquele elemento de imagem usando seu ID, como de costume. Portanto, temos uma variável apontando para a imagem da estrela aqui na linha 110. Vamos desenhá-lo no Canvas. Aqui em cima eu disse largura da tela de 500 pixels. O mesmo que eu tenho esse método de desenhar texto. Para manter nosso código organizado, criarei um método separado para desenhar a imagem. Não quero chamá-la de imagem de desenho porque esse nome já existe para um método Canvas embutido. Vou chamar esse método personalizado, por exemplo desenhe uma imagem de campo de fluxo para maior clareza. No interior, eu pego esses contextos de pontos e chamo o método de desenho de imagem embutido. Ele precisa de pelo menos três argumentos, a imagem para desenhar e as coordenadas x e y onde desenhá-la. Para testá-lo, chamarei de draw flow field image from inside render porque eu não sou definido em largura e altura online 148, a imagem está sendo desenhada em seu tamanho original. Podemos redimensioná-lo ou esticá-lo passando valores de largura e altura, 300 com 100 de altura. Que tal a largura total e a altura total da tela? Bom. E se eu quisesse que a imagem fosse centralizada exatamente no meio da cannabis, independentemente do tamanho que eu escolher. Isso também é muito fácil. Eu crio uma variável auxiliar chamada tamanho da imagem. Digamos que eu queira que a largura e a altura da imagem sejam 70% da largura da tela. Eu o uso aqui como largura e altura. Sim. Agora eu disse coordenada x até o meio da cannabis. Então essa largura de ponto vezes 0,5 e eu diminuo a metade do tamanho da imagem. A imagem está centralizada horizontalmente. Para a coordenada y vertical, eu faço a altura do Canvas vezes 0,5. O meio é mais ou menos verticalmente menos o tamanho da imagem vezes 0,5. Perfeito. Essa é uma fórmula muito simples para centralizar imagem no meio da tela HTML. Isso explica o fato de que as imagens no Canvas são desenhadas da mesma forma que retângulos do canto superior esquerdo, indo para a direita e para baixo, dependendo de sua largura e altura. Se eu redimensioná-lo agora para qualquer tamanho, ele sempre será desenhado no meio do Canvas. Eu farei 80 por cento da largura da tela, por exemplo, como expliquei antes, aqui criamos uma degradação do campo de fluxo, desenhamos algo no Canvas. Em seguida, analisamos esse tipo de nós com aquele texto, aquela forma ou imagem desenhada nele para obter dados em pixels para criar uma grade de campo vetorial a partir dele, convertendo cores em ângulos. Já temos toda essa lógica da parte anterior em vigor. Então, tudo o que preciso fazer aqui é substituir essa parte em que desenhamos texto código que desenha a imagem. Eu chamo desenhar imagem de campo de fluxo aqui e aqui vamos nós. Isso foi fácil. Eu realmente não quero desenhar a imagem real da estrela sobre ela assim. Em vez disso, eu parto daqui e quero desenhá-lo atrás das partículas somente quando o modo de depuração está ativo. Então, de dentro desse bloco de código, agora podemos ativar e desativar o modo de depuração pressionando letra D no teclado para mostrar e ocultar o campo vetorial, a grade e a imagem de origem. Eu posso mudar o tamanho da imagem. Podemos ver que está sempre centrado e que tudo funciona bem. Se eu redimensionar o Canvas, ele redimensionará a imagem com ele. Porque eu disse que o tamanho da imagem da estrela seria 80% da largura da tela. 40. Truques de manipulação de cores: Eu não poderia deixar isso e deixar você fazer seus próprios experimentos. Mas, novamente, eu estava brincando muito com o código e me perguntava como posso preservar e usar as cores originais da imagem de origem. Certo? Agora, estamos usando cores dessa matriz de cores de pontos na linha 25, as cores da imagem de origem em si não são visíveis. Além de usá-los para determinar os ângulos do campo de fluxo. Já estamos digitalizando essa imagem em busca de dados em pixels, então por que não tentar usá-la? Eu escrevi várias soluções diferentes para esse fim. Decidi mostrar este pelos motivos que explicarei à medida que implementarmos Se você tiver algumas ideias de como melhorar essa base de código, por favor, me avise. Em cada objeto de partícula, armazenarei uma propriedade separada para vermelho, verde e azul. Isso não é necessário se eu apenas tirou as cores da imagem original. Mas quando você vê o que isso parece, você provavelmente concordará que precisamos de uma maneira fazer a transição dinâmica e gradual entre as cores à medida que as partículas e linhas viajam de célula em célula pelo campo de fluxo. É por isso que precisarei das três cores separadamente, assim. Deixe-me te mostrar o porquê. concatenar a declaração de cores RGB aqui. Sinta-se à vontade para usar um modelo literal aqui. Em vez disso, se essa for sua sintaxe preferida, simplesmente farei RGB mais vírgula se essa for sua sintaxe preferida, , mais verde mais vírgula, mais bu mais colchete de fechamento. Agora, podemos mudar a cor das partículas lá dentro definindo esses dois valores diferentes. Ok, isso funciona bem. Eu vou até aqui dentro do método init, onde desenhamos o arquivo de imagem original no Canvas e o digitalizamos em busca de dados em pixels. Vou precisar de três valores para vermelho, verde e azul. Então, eu os disponibilizo inserindo-os como propriedades adicionais dentro da matriz de campos de fluxo. Então, agora é como um tipo de dados digitalizados de pixel, célula por célula, linha por linha. Cada vez que inserirmos uma nova célula na degradação do campo de fluxo, armazenaremos todos esses dados para cada célula na grade dentro de nossa matriz de campo de fluxo. Agora eu sei qual é o valor vermelho, verde e azul de cada célula individual na grade. Assim, posso combinar a cor das partículas com esses valores à medida que as partículas fluem sobre o Canvas. Dentro do método de atualização na classe de partículas. Nessa área, eu extraio o elemento desse índice específico dentro da matriz do campo de fluxo em uma variável só porque queria que a sintaxe desse bloco de código fosse mais fácil de ler. E também para desempenho, retirei esse índice da matriz apenas uma vez e, em seguida, uso essa referência existente em vários lugares. Agora eu posso substituí-lo aqui e aqui. Esse é o mesmo código. Acabamos de refatorá-lo. Portanto, nesta área, extraímos o valor do ângulo da matriz preenchida para lidar com o movimento das partículas. Nessa área, extrairei os valores de cor dessa célula no campo de fluxo. Eu só queria as células que contêm dados de pixels da imagem se elas tivessem alfa maior que zero, porque eu conheço as células transparentes com zero alfa ou o fundo ao redor da imagem. Não nos importamos com eles aqui. Portanto, se essa célula não for transparente, use essa propriedade de leitura de pontos nesse objeto de partícula. Definimos na linha 25 e a configuramos como propriedade de leitura que acabamos de extrair da propriedade de leitura do campo de fluxo contida nesta célula específica no campo de fluxo sobre o qual a partícula está se movendo no momento. Faremos o mesmo com esse verde escuro e esse azul escuro. Agora, quero usar esses valores de cor atualizados para construir a sequência de cores RGB novamente. Então eu copio a linha 28 e a uso aqui na linha 62. Bom. Estamos vendo as cores reais da imagem. Fazer isso requer muitos cálculos extras por quadro de animação, para nosso efeito. Mas cabe a você decidir se vale a pena ou se prefere usar cores predefinidas como fizemos antes, estou apenas mostrando o que é possível. Como sempre, tudo isso pode ser otimizado de várias maneiras diferentes. Técnicas avançadas de otimização estão fora do escopo desta aula, mas podemos falar sobre isso posteriormente em algum outro curso. Você pode ver que as linhas estão piscando. Você sabe por que isso acontece? É porque quando a partícula viaja da célula azul para a célula branca, por exemplo, a cor de toda a linha longa que a partícula está arrastando para trás mudará instantaneamente para essa nova cor. Ele mudará instantaneamente a cor de toda a linha porque cada linha é apenas uma chamada de sorteio. Então, podemos simplesmente mudar a cor de uma parte dessa linha com o código que escrevemos até agora. Novamente, várias soluções aqui. Eu poderia ajustar nosso código para verificar se a cor mudou. E então use essa cor atualizada apenas para alguns segmentos de linha. Ou o que vou fazer aqui, vou mudar a cor de toda a linha. Mas, em vez de essa mudança de cor acontecer instantaneamente, calcularei gradualmente a diferença entre as duas cores em várias etapas de animação. Portanto, as cores não mudarão apenas instantaneamente, elas passarão lentamente. Como fazemos isso com o código? Como estamos na seção avançada, usarei uma sintaxe simplificada mais avançada. Isso é chamado de operador ternário, o único operador JavaScript com três operandos. Nós o usaremos aqui como uma simples declaração de uma linha, caso contrário. Defina uma condição, uma expressão para avaliar. Se for verdade. Ponto de interrogação, faça isso. Caso contrário, se for falso, cólon, faça isso. Assim, à medida que as partículas fluem pela grade do campo de fluxo, elas extraem valores de cor dessas células. Eu verifico se o valor vermelho da partícula é o mesmo que o valor vermelho da célula no campo de fluxo nesse índice. Se for, simplesmente não faça nada e deixe como está. Se o valor vermelho não for o mesmo, em vez de reatribuí-lo instantaneamente ao novo valor de vermelho atualizado, aumentarei ou diminuirei gradualmente o valor vermelho em uma fração da diferença. Digamos que por um décimo da diferença. Poderíamos ter feito o mesmo com os valores de ângulo aqui, mas decidi que é mais eficiente em termos de desempenho usar um valor definido armazenado dentro do caractere angular, embora usar diferenças graduais de ângulo criaria curvas mais naturais no movimento das partículas. Você pode tentar isso mais tarde, se quiser. De qualquer forma, eu verifico se o vermelho é o mesmo que o vermelho novo. Se for, deixe como está. Se não for, aproxime-os um pouco mais, mas não de uma só vez para obter uma transição gradual. Não consigo ver se isso está funcionando ou não. Então, vamos fazer a mesma coisa com o verde. Assim. Eu tenho que ter cuidado com a sintaxe aqui. Acho que está funcionando. Vamos também fazer isso para azul. Assim. Estou apenas verificando meu código para ver se está tudo bem depois de tanto copiar e colar. Sim, isso é bom. Estou usando 0.1 aqui. Esse valor determinará o quão nítida ou gradual será a mudança de cor, a rapidez com que as cores passarão da cor existente para a nova cor alvo. Antes, a transição da cor acontecia instantaneamente para toda a linha de partículas multissegmentadas. Agora eles aconteceram gradualmente e o efeito parece bom. Eu acho que isso é muito especial. Não acredito que passamos de desenhar uma única linha animada para curvar formas de campo de fluxo ao redor das imagens. Se você acompanhou até aqui, essa é uma grande conquista, muito bem, e parabéns pela dedicação ao aprendizado. Você é um programador criativo, com certeza. Aqui na linha 86, posso controlar quantas partículas reiniciam dentro da forma e quantas reiniciam fora dela alterando quantas tentativas fazemos a cada partícula para tentar encontrar essa forma entre as redefinições. Para garantir que isso funcione, podemos usar uma imagem diferente. Novamente, lembre-se de imagens muito pequenas, se possível. Formas simples, como estrelas, funcionam muito bem para esse efeito. Você pode baixar a outra imagem que forneci na seção de recursos ou usar sua própria imagem. Agora, copio essa linha de código extremamente longa e vou indexar HTML. Precisamos que as linhas sejam quebradas para substituir a fonte. Então, se estiver tudo em uma linha para você, você pode acessar Exibir quebra de palavras para criar linhas de freio do VS Code Editor como esta. Para substituir a sequência de dados. No Visual Studio Code, posso simplesmente selecionar o início dessa string muito longa. Eu vou até o final. Eu pressiono a tecla Shift no meu teclado. E enquanto mantenho pressionada a tecla Shift, clico onde quero que a seleção termine. Ele destacará todos os textos intermediários e eu posso pressionar Delete. Bom. Agora que sei que excluí a imagem antiga, colo a nova sequência de dados base 64 da nova imagem. Eu o guardo. E aqui está, estamos desenhando uma imagem diferente e podemos ver as cores estão sendo extraídas corretamente dos dados de pixels de origem. Você pode conferir o código-fonte na seção de recursos abaixo. Também vou jogar com o código agora e incluirei alguns dos meus outros experimentos extras para você baixar e inspecionar se quiser inspiração sobre onde levar esse efeito ainda mais adiante. Gosto de projetos de codificação criativa porque estamos aprendendo sobre animação, bem como sobre o programa geral e os princípios. fizemos muitas funções de manipulação de matrizes Atualmente, fizemos muitas funções de manipulação de matrizes e, para loops, por exemplo, todas elas são muito importantes em todos os ramos da codificação, não apenas para animação. Muito obrigado por passar seu tempo comigo. Espero que você tenha tido muito valor hoje. Te vejo mais tarde.