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.