Transcripciones
1. Introducción: Las cosas geniales y hermosas con código pueden ser fáciles si
lo tomas paso a paso, todo tiene sentido si lo
divides en partes individuales, déjame mostrarte cómo tomar principios
básicos de programación, funciones, matrices y bucles
para crear bases complejas de código
animado. Una vez que entendamos completamente
las técnicas,
las llevaremos
al siguiente nivel en la sección avanzada. Hoy, descubriremos
las herramientas, genial, experimentaremos con código,
y usaremos ese conocimiento para diseñar
nuestras propias animaciones. Hagamos arte con código y aprendamos programación
al mismo tiempo. Que se diviertan.
2. Configuración de HTML y CSS: En esta primera sección, voy a crear un proyecto separado amigable para
principiantes. Aprenderemos a
animar líneas y cómo convertirlas en
múltiples efectos diferentes, como aligeramiento, espirales ,
ondas, etc. Si lo desea, puede saltar directamente a la sección de campo de
flujo, que comienza desde menos de 17. Incluí descargas de código fuente durante los puntos clave
de cada proyecto. Así que es más fácil para
ti saltar entre los proyectos y
experimentar con el código. Si eso es lo que quieres hacer, te
guiaré a través de
todo el proceso paso a paso, y te explicaré
cada línea de código, pero se necesitan algunos
conocimientos básicos de HTML, CSS y JavaScript
para obtener el máximo valor. Aquí, solo estoy configurando una página web genérica básica con elemento
HTML canvas en ella. Vinculé a los archivos style.css
y script.js. Y luego declaro algunos
estilos CSS para canvas y creo reglas de reinicio
globales para
asegurarme de que los márgenes y los paddings aparezcan iguales
en diferentes navegadores. Recomiendo usar
un navegador moderno para esta clase,
idealmente Google Chrome. Puedes ver que estoy usando esta posición absoluta
común, centro y técnica para
asegurarme de que Canvas esté en medio de la página web,
vertical y horizontalmente.
3. Configuración de JavaScript: Configuración básica dentro de
index.HTML y estilo CSS, nos movemos a script.js. Toda nuestra lógica
estará escrita aquí. Configuré mi elemento lienzo HTML, nuestro tablero de dibujo con las dos líneas de código
habituales. Creé una
variable personalizada que llamo e.g. canvas, y señalé
hacia el elemento canvas que creamos en index.HTML
usando su ID. Le di una identificación de Canvas uno. Después creo una variable de
contexto, CTX. Tomo esa
variable de lienzo que acabo de crear, y llamo al método
getContext incorporado en ella. Este método crea el
llamado draw in context, que es básicamente un objeto
JavaScript con todos los
métodos y propiedades de dibujo de Canvas incorporados. Le pasamos un argumento
llamado tipo contextos. Queremos trabajar con contexto de renderizado
bidimensional. Hoy en día, el elemento canvas tiene
dos tamaños independientes. tamaño del elemento, el
tamaño real del elemento HTML y el tamaño de la superficie de dibujo. Queríamos asegurarnos de que
ambos tamaños estén establecidos en
los mismos valores. Lo hago al no definir el tamaño del
lienzo en CSS y solo ciertos
atributos de
ancho y alto en Canvas
a los valores. Yo quiero así. Si también está declarando el tamaño del
lienzo en su archivo CSS, asegúrese de que esté configurado en
los mismos valores para evitar dibujos estirados o
distorsionados de otra manera. Si consola log c
dx desde la línea dos, podemos ver este lienzo renderizando el objeto de contexto del que hablé. En el interior. Podemos ver los ajustes predeterminados de
Canvas
como la fuente de estilo de relleno actual. Podemos ver que el estilo de trazo
predeterminado está configurado en negro aquí, por ejemplo, también
podemos ver todos los métodos de dibujo de
Canvas incorporados. Hoy, nos centraremos en
dibujar y líneas animadas. Entonces aprenderemos todo lo
que necesitas saber sobre método
begin path
que viene de aquí. También tenemos método de
ruta cerrada aquí, línea a aquí, y
pasar al método aquí. Usemos estos
métodos para que
entendamos completamente lo que
hacen y cómo funcionan.
4. Cómo dibujar rectángulos: Podemos dibujar muchas
formas diferentes en Lienzo, las formas
demasiado básicas son
círculos y rectángulos. Dibujar un rectángulo
es muy sencillo. Podemos tomar contextos que
definimos en la línea dos. Sabemos que contiene una referencia al objeto que contiene
todos los métodos de dibujo de lienzo. A partir de ahí llamamos método de rectángulo de
relleno incorporado. Rellenar rectángulo
espera coordenadas partir de las cuales comenzaremos
a dibujar en
el rectángulo, la esquina superior izquierda
del rectángulo. Coordenada X, la distancia
de la esquina superior izquierda del rectángulo
desde el borde izquierdo del lienzo
será de 100 píxeles, y coordenada, la distancia desde la parte superior también será de 100 píxeles. El ancho del
rectángulo será 50 píxeles y la
altura será de 150. Puedo cambiar el
ancho a 200 píxeles, coordenada
vertical y
250 píxeles. Creo que se entiende la
idea por defecto, el relleno de las formas dibujadas
en Canvas se establece en negro. Puedo usar la
propiedad FillStyle para anular el valor predeterminado y puedo
configurarlo en otra cosa. Vamos a probar el rojo. También podemos llamar método de rectángulo de
trazo incorporado, que simplemente
delinear la forma. Por defecto, será
línea negra con un ancho de píxel. Puedo cambiar eso usando la propiedad
de ancho de línea. Vamos a probar diez píxeles. Y puedo usar un estilo de trazo
para cambiar el color de todas las líneas dibujadas en
Lienzo, por ejemplo, azul.
5. Cómo dibujar líneas: Entonces estos son los conceptos básicos
de dibujar formas en Canvas. Hoy, nos centraremos
en trazar líneas. Funcionan un poco
diferente a los rectángulos. Tenemos que comenzar por dos puntos método de ruta de inicio
incorporado. Este método iniciará una
nueva ruta y también cerrará automáticamente toda la ruta
existente si la hay. Esto es importante porque de
esta manera puedes dibujar cada línea en un
color diferente y sin comenzar camino, todas tus líneas
se
unirán automáticamente en una forma masiva, que no es lo que queremos hoy. ¿Verdad? Ahora, solo
queremos trazar una línea simple. Comenzamos por usar el método
incorporado move to. Este método creará una nueva subrayectoria para nuestros
propósitos y propósitos. Pensemos en pasar a
métodos como una forma de establecer las
coordenadas x e y iniciales de nuestra línea. Entonces usaremos la línea
a los métodos que
crearán una línea recta
desde el subcamino, desde el punto definido
en movimiento hasta dos, las coordenadas
pasaremos a la línea dos. Pensemos en ello por ahora
que la línea dos métodos
representarán las coordenadas x e
y finales de nuestra línea. Mover a la línea final dos métodos
sólo definen la ruta. No renderizan directamente nada para dibujar
el camino sobre nosotros, tenemos que usar el método de
trazo incorporado. Ahora, estamos dibujando una línea
a partir de las coordenadas 300, 302, coordenadas 350, 400. Podemos cambiar estos
valores para cambiar dónde comienza
nuestra línea
y dónde termina. Puedo borrar el rectángulo. Ahora bien, en esta área, quería definir escenarios
globales. El ancho de línea será de
diez píxeles o 100. Muevo las coordenadas. Tenemos muchas otras
propiedades que podemos usar aquí. Puedes verlos todos
si la consola registra CTX desde la línea dos como lo
hicimos antes, por ejemplo, mira lo que sucede cuando dije la propiedad
Line Cap para redondear. Configuré el
estilo de trazo en magenta, ancho de
línea en diez. También podemos encadenar múltiples
líneas dos métodos como este. Cada nueva línea dos métodos, vamos a definir otro
punto en la forma que se conectará
con nuestro subpath. Y escribió el dentista, este es el concepto principal de
animación que estamos haciendo hoy. Tendremos una línea
que empieza en alguna parte. Entonces tendremos
muchas llamadas de la línea dos a los puntos de hallazgo a
lo largo de ese camino. Y similar al
clásico juego de serpiente, vamos a animar esto
agregando siempre un nuevo segmento de línea al inicio y eliminando
el último segmento, Haciendo que parezca que la línea
se arrastra por la pantalla. Añado una nueva línea. Añado uno más. Elimino el segmento más antiguo, agrego otra línea nueva. Automatizaremos esto y jugaremos con
las coordenadas que
pasemos a estas líneas para crear interés en los patrones de
movimiento. Una vez que entiendas
este concepto, lo
usaremos para construir hermosos campos de flujo como
este en una clase avanzada. Podría ser
más fácil de lo que piensas hacer que las líneas fluyan alrededor de
imágenes o letras.
6. Programación orientada a objetos: Ahora que entendemos el
concepto, vamos a escalarlo. Quería crear una clase JavaScript
personalizada que dibujara y
animara líneas para mí, quería animar muchas
líneas al mismo tiempo. Entonces usar una clase es ideal aquí. El constructor de clase es un método especial para crear una
instancia de una clase. Cuando lo llamamos con la nueva palabra clave later
class constructor, crearemos un nuevo objeto JavaScript
en blanco, y establecerá
sus propiedades y valores basados en el
blueprint interior. Entonces definamos ese plano. Quiero que empieces muy
sencillo y vamos a optimizar el código después para asegurarnos de que quede
absolutamente claro lo que está pasando. Cada objeto de línea tendrá las coordenadas x e y
iniciales. Entonces, una propiedad personalizada que llamo, por ejemplo start x será un punto
aleatorio entre cero y ancho horizontalmente. coordenada vertical inicial
de cada línea será un valor aleatorio entre cero y una especie de
altura vertical. Entonces, cuando combinamos estas coordenadas x e y
aleatorias, nos
dará un punto en algún lugar
dentro del área del lienzo. Quiero hacer lo mismo para
terminar las coordenadas x e y así. Entonces, cuando se crea un nuevo
objeto de línea, se
le asigna aleatoriamente el punto de
inicio y el punto final. Vamos a darle un método de dibujo
personalizado para trazar una línea entre
estos dos puntos. Yo llamo comenzar camino primero. Mover al método para definir las
coordenadas x e y iniciales de la línea. Método de la línea dos para definir coordenadas x e y
finales de la línea. Y llamamos trazo para renderizar
realmente ese
camino en Canvas. Tenemos una clase, nuestro
plano está listo. ¿Cómo lo usamos realmente
para crear un objeto de línea? Yo creo una variable constante, llamo a la línea uno. Lo puse igual a
nueva línea así. La nueva palabra clave
buscará una clase con este nombre y activará
su constructor de clase. Constructor de clase, crearemos un nuevo objeto JavaScript en blanco, y le asignará valores y propiedades
basados en el blueprint dentro de ese objeto se guardará en disgusto ellos
línea una variable. Dado que este objeto fue creado
usando la clase de línea, tiene acceso a este método de dibujo
público y
puedo llamarlo así como esta
línea un dibujo de punto, se
calcularon las coordenadas de inicio y
finalización
aleatorias y
se dibujó una línea perfecta. Arriba en la línea siete, ancho de línea
incierto
a diez píxeles. Pero tal vez quiero que
cada línea creada por la clase tenga un ancho aleatorio dentro de
un rango predefinido. Creé esta propiedad de ancho de
línea de puntos, y será un
valor aleatorio, 1-16 píxeles. Lo envolveré en Math.floor para que no
obtengamos valores de subpíxeles. Es un buen hábito hacer eso por
todo lo que dibujamos en
Canvas siempre que sea posible. También podría haberlo hecho
para las coordenadas x e y. Tomo CTX de línea a ancho de
línea y lo configuro a este valor de ancho de
línea aleatorio. Ahora, cada vez que actualice la ventana de
mi navegador, alinearme con la posición aleatoria y se dibujará el
ancho de línea aleatorizado. Estamos haciendo algo que aquí
se considera una mala práctica. Definí la
variable canvas en la línea uno, y estoy usando esa misma variable directamente dentro de mi clase. Yo hago lo mismo con la variable ctx. El código funcionará, pero si estás escribiendo código
orientado a objetos, el objetivo es mantener a tus clases independientes de su entorno
léxico, independiente del código que está
fuera de la clase misma. ¿Correcto? Ahora bien, esta clase sólo
funcionará si aquí
se definen las variables
Canvas y CTX. La forma correcta de
hacerlo es convertir estas variables externas
en propiedades de clase. De esa manera, se
pasará
al constructor de clase aquí
cuando se cree la clase. Y pueden venir de
cualquier parte de nuestra base de código, haciendo que nuestra clase sea más
autónoma y reutilizable. A menudo me preguntas por qué
hago esto en los comentarios, así que espero que esto lo explique. constructor de clase de línea
esperará el cannabis como argumento. En el interior. Convierto ese argumento
en una propiedad de clase. Estoy diciendo tomar la variable canvas que se pasó
aquí y
convertirla en propiedad Canvas en esta instancia de clase de línea
que estás creando en este momento. Entonces podemos usar este punto
Canvas de la línea 12 aquí, en lugar de tirar directamente de
la variable de la línea uno. Para que todo esto funcione, sé que el constructor de
clase de línea nos
espera como argumento. Entonces tomo la
variable canvas de la línea uno y la paso como
argumento aquí. Cuando creamos una
instancia de esa clase con la nueva palabra clave perfect, también
estamos tirando directamente de la
variable CTX de la tierra
a nuestra clase aquí. Por lo que nuestro
método de sorteo público esperará contexto como argumento
y se utilizará aquí. Después tomamos CT
x-variable de la línea dos y la pasamos a
dibujar método aquí abajo. Cuando lo llamamos así, CTX se
convertirá en contexto aquí. Entonces así es como haces que
las clases sean más autoencerradas y menos dependientes
del
frío circundante fuera de esa clase.
7. Colores dinámicos con HSL: Estamos definiendo el
estilo de trazo en la línea ocho, pero tal vez quiero que
el color de las líneas también sea
aleatorizado. En ese caso, tengo que definir el estilo de
trazo dentro
del método de dibujo aquí. Dije que es para
escribirlo solo para probarlo. Si está funcionando. Quería asignar
un color aleatorio cada vez que creamos una nueva línea. La forma más fácil de
hacerlo es mediante
el uso de la
declaración de color HSL en la web, podemos definir colores de
muchas maneras diferentes. Tienes tus declaraciones de color RGB
y hexadecimal estándar con las que todos están familiarizados. También podemos usar declaración de
color HSL, matiz, saturación, luminosidad. El primer argumento aquí, representarás un grado
en la rueda de colores 0-360. La saturación será del 100 por ciento. Queremos colores completos. La ligereza será del 50 por ciento. Queremos un color no
afectado por la luz u oscuridad. Cero grados en la rueda de colores
es correcto, como puedes ver, 120 es verde, 240 es azul, 360. Volvimos al rojo en bicicleta. Otra vez. A medida que aumentamos la vista, viajamos por todos los
colores intermedios. Si vamos más altos que 360, simplemente
volvimos a pedalear
desde el principio desde el color rojo. La declaración de color
Hsl está estructurada de una manera
que hace que sea muy fácil aleatorizar colores o ciclar
dinámicamente a través
del espectro de color. Creo una propiedad de
clase personalizada. A esto lo llamo punto vista. Será un valor aleatorio 0-360, y quiero solo enteros. Entonces Math.floor, haremos que el estilo de
trazo sea dinámico
reemplazando el valor de tono codificado con esta
variable aleatoria como esta. Y eso es todo. Cada vez que refresco la página, calculamos aleatoriamente
un color diferente.
8. Arte aleatorizado en línea: Como decíamos, la
clase JavaScript es un blueprint. Podemos usarlo para crear
muchos objetos similares. Entonces, ¿por qué estamos creando una
sola línea aleatoria? Vamos a crear muchos más. En este punto, es muy fácil. Primero creo una variable
llamada matriz de leones. Esta será una matriz para mantener todos los objetos de la aerolínea
en un solo lugar. Ahora puedo crear un for-loop. Ese bucle for se ejecutará por ejemplo diez veces. Cada vez que se ejecuta, tomo la matriz de líneas y llamo al método push de matriz
incorporado. Método Push. Tomaremos
lo que le pasemos como argumento y
lo empujará hasta el final de la matriz. Le pasaré una nueva línea. Y en línea 11, puedo ver que constructor de clase de línea espera Canvas como argumento. Así que le paso canvas
variable de la línea uno. Elimino este código, y me consolar el array de líneas de registro. Como era de esperar, contiene diez objetos de línea creados
usando nuestra clase de línea personalizada. Abro uno e inspeccioné para asegurarme de que todas las
propiedades tengan valores. Quiero que compruebes que
nada está indefinido, lo que sería una señal de un
problema. Todo está bien aquí. También puedo crear
un número de líneas, una variable, y la configuro en 50. Lo uso aquí en el for-loop. En la consola, puedo ver
que la matriz de líneas ahora contiene 50 objetos de línea con posiciones
aleatorias,
ancho de línea y colores. ¿Cómo los dibujamos? Dado que estamos sosteniendo todos los
objetos align dentro de la matriz de líneas, simplemente
podemos llamar a
una matriz incorporada para cada método en él, para cada método llamará a una función de devolución de llamada proporcionada
una vez para cada elemento de la matriz. Así que dentro, para cada
objeto de línea en la matriz, quiero llamar a su método de dibujo
asociado que definimos en la línea 20. Si te estás preguntando de dónde viene
esta palabra objeto,
es solo una
palabra aleatoria que elegí usar. Básicamente somos un inicio de sesión en
cada objeto de la matriz, un nombre de variable que se
utilizará para hacer referencia a ese objeto dentro de
este para cada método, ese nombre de variable puede ser cualquier cosa siempre y cuando
sigamos refiriéndonos a él de esa manera en todas partes
dentro de este método de devolución de llamada, también
puedo llamarlo línea por ejemplo así para cada objeto de línea dentro matriz de
líneas llamado
su método de dibujo. En la línea 20, puedo ver que el método draw espera
contexto como argumento. Entonces le paso variable CTX. Definimos en la línea dos. Estamos dibujando 50
líneas sobre Lienzo. Cada uno tiene coordenadas de inicio
y finalización
aleatorias, ancho aleatorio y color. Puedes refrescar la página
para generar un nuevo conjunto de valores aleatorios y
dibujarlos en Canvas. Enhorabuena si este es tu primer proyecto de
codificación creativa, esta es una forma muy sencilla de arte generado por
procedimiento, el
llamado arte generativo. El arte generativo es
una colaboración entre un ser humano y una máquina. Las reglas y alcances de esta obra son decididas por nosotros, los humanos. Pero algunas de las características, en este caso colores
y posiciones, son decididas aleatoriamente
por una computadora. Por supuesto, hay formas
mucho más avanzadas de arte generativo. E hice muchas clases donde
exploramos eso de diferentes maneras. Veamos a dónde
podemos llevar esta. Vamos a animarlo.
9. Dibujo de líneas multi-segmented: Para mayor claridad, volveré a una línea para que podamos
ver mejor lo que está pasando. Como dijimos al principio, quería tener una línea
hecha de múltiples segmentos. Estaremos agregando nuevos segmentos y quitaremos unos viejos para que parezca que se
arrastra como el
clásico juego de serpientes. Necesito hacer algunos cambios en la clase de línea para lograrlo, solo
necesitaremos un conjunto de coordenadas
x e y, así. Estas coordenadas se
actualizarán para cada tick del bucle de animación
y agregaremos y mantendremos un cierto número
de posiciones en una matriz de historia
que defino aquí. Primero, será un objeto
simple con propiedad x e
y igual a este
punto x y este punto y acabamos de aleatorizar aquí. Este historial de nodos
es un objeto ahora, pero será una matriz
donde cada elemento esa matriz es un objeto como este con las coordenadas x e y. El método Move to definirá las
coordenadas x e y de inicio de nuestro camino. Y será este índice de matriz de
historia de puntos cero, que será objeto así. Y accedemos a su coordenada x
y también a su coordenada y. Digamos que voy a mantener diez
objetos dentro de la matriz de historia. Cada uno tiene su valor de posición x
e y. Aquí quiero recorrer
sin importar cuantas posiciones tengamos
en la historia array, y quiero
conectarlas con una línea. Así que creo un bucle for que
se ejecutará tantas veces dependiendo de la longitud de
esta
matriz de historia de puntos desde la línea 15. Y cada vez que se ejecute, tomará objeto, que se verá así
en ese índice en la matriz, y pasará sus
coordenadas x e y al método de la línea dos. Así que nos hemos movido
al método para establecer la
posición x e y inicial de la línea. Y luego recorremos todas las demás posiciones y las
conectamos con una línea. Entonces llamamos trazo para renderizar ese
camino multisegmentado en Canvas. Aún no tenemos bucle de
animación, así que crearé
otro bucle for que simplemente ejecutaremos tres veces y crearemos tres posiciones x e y
aleatorias. Necesito asegurarme de que
la historia de la piedra aquí
arriba sea en realidad una matriz. Al principio, contendrá solo un elemento con
un índice de cero. Será este objeto el que
tenga las propiedades x e y establecidas en estas coordenadas de punto x
e y. Aquí corro un for-loop
tres veces. Cada vez que se ejecuta, creo nuevas posiciones
x e y aleatorias. Tomo distorsionar la matriz de historia y empujo otro objeto con estas nuevas propiedades x e y en su cuidado con
los corchetes aquí. Bonito. Cada vez que actualizo
la ventana del navegador, dibujamos una nueva línea de múltiples segmentos comenzando las coordenadas x e y. Y para bucle que se ejecuta 123 veces cada vez que crea un segmento de
línea, una subruta. Puedo hacer que el for-loop
se ejecute 30 veces si quiero, lo que creará una forma mucho
más compleja. Espero que quede claro ahora cómo funciona
el concepto de matriz de
historia. Ahora vamos un paso
más allá para animarlo.
10. Líneas animadoras: Creo una
función personalizada a la que llamo, por ejemplo, animar. En el interior,
trazaremos una línea. Lo actualizaremos. Y luego llamamos marco de animación de
solicitud incorporado, que le dice al navegador
que queremos realizar una animación. Esto hará que el navegador
llame a una función que
especificamos antes del siguiente repintado. En la práctica, esto significa que simplemente le
paso el nombre de
su función padre, animo carreras, hace algo y luego
solicito fotograma de animación. Volveremos a llamar a animar, creando un bucle de animación
repetitivo sin fin. Solicitar el método de marco de animación
se ajusta al objeto de ventana, pero se puede llamar
directamente así. Entonces aquí definimos animar.
Tengo que llamarlo. Para iniciar el primer bucle de
animación. Pongo un registro de consola dentro
que dice animando, solo para comprobar que el loop realmente
se está ejecutando. Sí, eliminé. Quiero poner nuestro
código de sorteo dentro así. Esto es solo crear un crecimiento
interminable en línea. Podemos comentar temporalmente
esquema para los siete. Si tu computadora
lucha con esto, lo
arreglaremos en un segundo. Quiero eliminar pintura vieja entre todos los fotogramas de animación, así que llamo método de rectángulo
claro incorporado. Quiero borrar todo el
lienzo desde la coordenada cero-cero hasta el
ancho del lienzo, la altura del lienzo. Bien, comento esto
porque estamos agregando 30 segmentos de línea una y
otra vez en matriz de
historia aquí en la línea 20 para crear un
interminable grow in array, creo un método de actualización en la clase de línea para
cada fotograma de animación, cada vez que se ejecuta el método de actualización, quiero agregar uno nuevos
segmentos a nuestra línea. Voy a borrar todo esto. Descomento la línea 47. Y por cada tick de animación, quiero que llamen al método de
dibujo en cada objeto dentro de
la matriz de líneas. Actualmente, solo tenemos
un objeto ahí dentro. También quería llamar al método de
actualización que acabamos de definir. Ahora podemos ver línea se
dibuja segmento por segmento. No tiene sentido
recorrer la misma
matriz dos veces aquí. Entonces, en cambio, llamo dibujar y actualizar en la misma función de
devolución de llamada. Cuidado con los corchetes aquí. ¿Es para cometer un error
y obtener un error? Bonito. No quiero que esté
dibujando un camino con una
cantidad de puntos infinitamente creciente. Quiero tener
cierta longitud máxima. Y cuando se llegue a eso, eliminaremos el
segmento más antiguo y agregaremos uno nuevo. Digamos que quiero que el camino
tenga diez segmentos de largo. Método de actualización interna. A medida que agrego un nuevo segmento, verifico si la longitud de matriz
histórica es
mayor que la longitud máxima. Si es más de diez, usaremos el método de desplazamiento de
matriz incorporado. El método de desplazamiento de matriz elimina
el primer elemento de la matriz porque estamos usando método
push para agregar
un nuevo segmento. El método Push agrega un nuevo elemento
al final de la matriz. El método Shift eliminará el segmento más antiguo para nosotros desde el inicio
de la matriz. Y aquí llegamos
al segundo paso en nuestra línea
procesal art. ¿Qué opinas de esto? Escala, pero con reglas, podemos agregar tantas
líneas como queramos. Todos tienen ancho y
color
aleatorios debido a la lógica
que escribimos al principio, solo
estamos recogiendo
puntos al azar dentro del cannabis. ¿Y si queremos alguna sensación
de movimiento continuo? Queremos que la posición actualizada
del siguiente segmento tenga alguna relación con la posición del segmento
anterior. Esto nos está
acercando un paso más a un campo de flujo real. Espero que estés
obteniendo algo de valor. Exploremos el movimiento y ahora pensaré en nuestra
línea como una partícula. Su primer segmento
se mueve a lo largo del lienzo en cierta
velocidad y dirección. Los otros segmentos siguen. Doy a cada línea velocidad X, velocidad
horizontal y velocidad. ¿Por qué la velocidad vertical? Comenzaremos desde
un punto aleatorio en algún lugar dentro del área del lienzo. Y cada vez que
llamamos método de actualización, aumentamos la
exposición actual por el valor de velocidad x y posición vertical y
por el valor de velocidad. ¿Por qué? Insight animation
loop Voy a descomentar, dibujar y actualizar para
ver lo que acabamos de hacer. Bien. Yo creo 20 líneas. Sí. Esto es lo que está pasando.
11. Efecto de tormenta de rayos arco iris: Voy por el efecto de aligeramiento. Quiero una tormenta
relámpago arcoíris. Cada vez que actualicemos la posición
horizontal por velocidad x de diez píxeles, además de eso,
agregaremos un valor aleatorio 0-10 y 50. ¿Qué pasa con un valor aleatorio
entre -25 y más 25 horizontalmente y los mismos intereses
verticales Entonces cuando refresco mi página, me sale un juego de relámpagos muy
cortos. Si quiero que vayan más
de arriba a abajo,
tal vez la velocidad horizontal
sea solo más u2 y la velocidad vertical 15 o 46. Me gustaría que la animación
se reproduzca y luego se restablezca. Podría, por ejemplo, verificar si todos los
segmentos salieron del área del lienzo. O puedo darle un temporizador a cada línea. Digamos que cada línea
tiene una vida útil de longitud máxima desde la
línea 18 por diez, cada línea se moverá
durante 100 fotogramas de animación. Dentro del método de actualización,
aumentaré el temporizador en uno por cada fotograma de animación.
¿Cómo hago esto? Si el temporizador es menor que la vida útil? Animamos la línea. También necesito definir este temporizador de puntos en el constructor de
clase aquí arriba. E inicialmente lo puse a cero. Cuando el temporizador es
más que vida útil, seguimos dibujando las líneas, pero ya no estamos agregando
y quitando segmentos, así que parece
que se congelaron en el espacio. En ese punto, quiero comenzar
a eliminar segmentos uno por uno hasta que desaparezca
la línea. Entonces si no, y aquí
volveré a llamar turno en
la matriz de historia. Tened un segundo conmigo. Necesito elaborar
la lógica aquí. Tenemos que
asegurarnos de que
siempre haya al menos un
elemento en la matriz. De lo contrario, si esta longitud de punto
histórico de puntos es menor o igual que uno,
llamado método de reinicio. Vamos a definir el método de reinicio. Ahora bien, ¿funcionará esto? El temporizador está aumentando siempre y cuando el temporizador sea
menor que la vida útil, agregue y elimine posiciones, haciendo que la línea se arrastre alrededor. Si la longitud es menor o
igual a uno, restablecerla. contrario, es decir, el temporizador
es más que la vida útil, pero la longitud aún no es
menor o igual a uno. Sigue eliminando un
segmento a la vez. Creo que esto debería funcionar. Ahora necesito definir el
método de reset que acabaremos de establecer la línea de nuevo a su estado inicial para
que podamos animarla. Otra vez. Tendremos que
restablecer la posición x e y, y agregaremos esa posición
inicial dentro de la matriz de historial. También reiniciaremos el temporizador a
cero para que pueda volver a contar. Estoy recibiendo un error de consola. Probablemente note
esto antes de que necesite llamar a un turno para eliminar el primer segmento
de la matriz en la
matriz de historial real. Así. Sí, esto es lo que quería. Las líneas se mueven alrededor de
400 fotogramas de animación y luego se reinician. Todos se reinician al
mismo tiempo porque
codificamos duramente maxlength para que sea el mismo valor para todos ellos. Lo configuré a un
valor aleatorio, 10-160 segmentos. Ahora estamos obteniendo cierto
sentido de movimiento. También puedo aleatorizar la velocidad x, digamos un valor aleatorio entre
-2.5 y más 2.5 velocidad, y será seis. Velocidad. ¿Por qué diez? A lo mejor aquí debería hacer valor aleatorio
entre -0.5 y más 0.5. Velocidad Y5 siete. También puedo jugar con el rango
aleatorio aquí y aquí. Generar
números aleatorios como este para cada fotograma de animación es muy caro para el rendimiento,
solo para que lo sepas. Pero como no tenemos
miles de líneas, la
mayoría de las computadoras
probablemente ni siquiera notarán reducir cuántas
veces tus
llamadas de base de código dominaron el marco de animación de
pares aleatorios aumentará masivamente el
rendimiento de tus efectos. Dije vida útil a
longitud máxima por tres. Se puede ver que tenemos una línea que parte de un segmento. Crece hasta
alcanzar la longitud máxima, luego llama a un
máximo de tres términos. Es maxlength. En ese punto, ya no crece. Se encoge desde el último
segmento desde el final, y luego desaparece
y se restablece. Este tipo de
movimiento de línea es exactamente lo que necesitas para
crear campos de flujo. Ahora bien, una forma
de implementarlo. Yo creo 100 líneas. Esta es mi versión de tormenta relámpago
arcoíris generada por
procedimientos. Si eres principiante y has
seguido todo el camino hasta aquí, ahora
eres un corredor creativo con un conocimiento del lienzo HTML. Enhorabuena, siéntete libre agregar este proyecto,
tu currículum en línea.
12. Degradado lineal: Html canvas ofrece tantas herramientas integradas
diferentes que nos permiten
modificar nuestras animaciones. Acabamos de construir el efecto de tormenta
relámpago arcoíris. Las líneas que estamos dibujando
en Canvas son solo formas. Déjame mostrarte cuatro formas
muy diferentes cómo puedes mejorar el relleno y trazo de tus formas usando gradientes, imágenes y sombras. Html canvas ofrece dos
métodos para dibujar gradientes. Podemos utilizar el método de crear gradiente
lineal. Es muy sencillo de
usar. Déjame mostrarte. Crea un degradado
a lo largo de una línea que conecta dos
conjuntos dados de coordenadas. Primero dos argumentos,
le pasamos nuestras coordenadas x e y
del punto de inicio. Quiero que mi gradiente comience
en la coordenada cero-cero. Y yo quería que el punto final estuviera en coordenadas lienzo
ancho, alto. Dibujamos una
línea invisible de aquí a aquí. El gradiente se dibujará
a lo largo de esta línea. Para trabajar con gradientes, ayuda a
guardarlo en una variable. Yo lo llamo por ejemplo gradiente uno. Entonces tomo esa
variable y llamo al método
incorporado add color
stop en ella. Aquí definimos offset y color. Entonces en el desplazamiento cero al
inicio del gradiente, quería comenzar desde el rosa. Copo esta línea algunas veces. Empecemos en el desplazamiento 0.2. En realidad, se leerá 0.3. 0.4 es naranja, 0.5
es el amarillo. 0.6 será verde. 0.7, turquesa, 0.8 es
violeta. Eso es suficiente. Creo que tomaría esta
declaración de estilo de trazo y la
puse aquí después de
definir el degradado. Y lo pondré a
la variable que contiene nuestro degradado
lineal recién definido. Observe que no hay comillas, solo el
nombre de la variable así. También necesito comentar la línea 33 para que se aplique nuestro
gradiente. Como puede ver, estamos dibujando
un degradado lineal desde coordenada cero-cero hasta el ancho del
lienzo, la altura del lienzo. Yo creo 200 líneas. Esta es una versión muy diferente de la
tormenta relámpago arcoíris, ¿no?
13. Degradado radial: Copio esta línea de código. Yo lo llamaré gradiente a. También hemos creado un método de gradiente
radial. Este espera
al menos seis argumentos, x e y del punto central
del círculo de inicio interno
y su radio. Quiero que el punto
central del círculo esté en medio de Canvas. Entonces, el ancho del lienzo es de 0.5, alto del
lienzo por 0.5 y el radio será de 30 píxeles. El círculo final también
estará comenzando en el centro de la lona
con un radio de 200. Se lo doy a las paradas de color solo para mostrarte cómo se ve
eso. Creo que ya entiendes
este concepto de todos modos. A 0.4 offset, tendremos verde desde 0.6, será azul. Después configuro el
estilo de trazo en la herramienta Degradado. Aquí. Puedo cambiar
el valor del radio. Puedo agregar parada de color aquí. Entonces así es como se usa el gradiente
lineal y radial.
14. Cómo rellenar formas con un patrón: A medida que estamos llenando nuestras
formas con gradientes, podemos llenarlas con un patrón. Ese patrón puede ser algo que
dibujemos en un lienzo fuera de la pantalla, pero también podemos usar una imagen. En index.HTML. Yo creo un elemento IMG. Le doy una identificación
de imagen de patrón. Como fuente, normalmente
usaría una ruta hacia ese archivo de imagen, pero eso
nos daría problemas si
ejecutamos nuestro código localmente
solo desde una carpeta sin usar un servidor para evitar problemas de uso compartido de
recursos entre orígenes, convertiré la
imagen real en código base 64, y haré que ese código sea
parte de nuestro archivo HTML índice. Cuando haga eso, la
imagen será considerada el mismo origen
en todos los escenarios. Así que no tengo que lidiar
con nada sitio servidor. En este curso, quiero enfocarme en el desarrollo
web front-end. Preparé una imagen que puedes descargar en la sección de
recursos a continuación, la
hice del mismo
tamaño que nuestro lienzo. También podemos usar tu
propia imagen si quieres. Puedo usar JavaScript
para convertir la imagen en cadena de datos base-64
dibujándola en Canvas y usando dos URL de datos método incorporado. Pero por simplicidad, voy a usar un sitio web para hacer eso por mí, hay muchos
sitios web que pueden convertir las imágenes
en código en segundos para nosotros, solo
voy a Google
y busqué
PNG para basar la frase 64. Voy a elegir este enlace
en línea PNG tools.com. Arrastre y suelte la
imagen que quiero convertir aquí y me genera
una cadena de datos. Tenemos que asegurarnos de que la
cadena comience con la base 64. Si no cae, da clic en esta casilla de verificación para obtener
el formato correcto. Copio todo este bloque de código. Es mucho código dependiendo de qué tan grande sea la imagen
que estés usando. Lo pego aquí dentro del argumento
fuente, dentro como RC. En Visual Studio Code, puedo ir a View
where drop para poner esta línea extremadamente larga
de código en una línea, facilitando la
navegación en este archivo de código. Voy a estilo CSS. En realidad guardé los cambios en index.HTML y
se puede ver que
estamos dibujando la imagen
en la página web sin necesidad del archivo de imagen
real. El código que acabamos de generar
reemplaza
completamente el archivo de imagen y contiene toda la información de píxeles
sobre esa imagen. Oculto la imagen con CSS
usando su ID display none. Bien, tenemos una
imagen que podemos usar. Entonces en esta área, definimos los gradientes. Aquí, vamos a crear un patrón. También es muy fácil. Voy a necesitar una referencia
a ese elemento IMG acabamos de crear en index.HTML. Creo una variable a la que
llamo pattern image, y apunté JavaScript hacia el elemento IMG usando su ID. Otra variable que llamo patrón
uno es igual al punto ctx. Y aquí usamos el método de
creación de patrones incorporado. Este método funciona de manera
muy similar a los dos métodos que utilizamos
para crear gradientes. Se necesitan dos argumentos,
imagen y repetición, y luego podemos
usarlo como FillStyle
o estilo de trazo para llenar nuestras
formas con esa imagen. Déjame mostrarte cómo se ve
eso. La imagen a dibujar será la
imagen de patrón que acabamos de crear. Y la regla de repetición no
será repetida. Ahora simplemente configuro un
estilo de trazo en el botón uno. Y aquí vamos. Podemos ver que nuestras líneas ahora están
llenas de una imagen. Esta técnica
se puede utilizar como una forma de
revelar una imagen, por ejemplo, dependiendo de qué
tipo de aplicación o efecto estés construyendo, también
podemos usar un mosaico sin costuras como imagen para crear
un patrón repetitivo, que es probablemente para lo que se diseñó este
método. Como propósito principal, puedo usar líneas más anchas para
ver más de la imagen e.g
15. Mejora tus efectos con sombras: Me gusta usar
las sombras de Canvas para obtener a mis formas un sutil efecto 3D. Dije desplazamiento de sombra
a dos píxeles. Esto definirá la
distancia entre sombra y la
forma horizontalmente. Desplazamiento de sombra y, la distancia
vertical también
será de dos píxeles. Esto puede ser valores positivos o
negativos, por cierto, dependiendo de qué lado, relativo a la forma que
quieras que sea la sombra. El color de la sombra será blanco. Esto nos dará estas
interesantes grietas afectan o reducen el
número de líneas. Bloque de color de sombra. Puedo volver al gradiente
uno, el gradiente lineal. Ahora podemos ver mejor
qué está
haciendo la sombra y cómo
resalta los bordes. Si tienes algún
problema de rendimiento y caídas de FPS, la forma más rápida de solucionarlo es reducir el número de
líneas que estás animando. Y también puedes
desactivar estas sombras. Suministro y ancho
a un valor menor. Nuestra
tormenta relámpago arcoíris puede tomar muchas formas, y creo que
ahora tienes
muchas herramientas para ajustarla y
hacerla tuya. Hagamos algo completamente
diferente con esto. Ahora. ¿Qué tal en lugar de
relámpagos, quiero espirales Hablemos de trigonometría. Como siempre, es posible que
desee crear una copia de su código para guardar este efecto
para una referencia futura, haremos cambios
radicales en el código ahora y lo
transformaremos lo
transformaremos una obra de arte
generativa completamente diferente.
16. Trigonometría: La trigonometría tiene que
ver con los ángulos. Quiero que cada objeto de línea
tenga su propia propiedad de ángulo. Entonces lo defino aquí. Por cada fotograma de animación, estaré aumentando sin cesar
ese valor de ángulo en 0.1. Este valor
representará radianes. Entonces, en lugar de hacer este efecto de
aligeramiento aquí, voy a aumentar x por signo Masdar y le paso este valor de ángulo
cada vez mayor. Esto creará un movimiento
horizontal a la izquierda y a la derecha como este. El análisis y cada aumento
en el valor a metóxido simplemente
mapearán estos
valores a lo largo de una onda sinusoidal. ¿Y si quiero que las olas
vayan más a la izquierda y a la derecha? Creo una propiedad llamada esta curva punteada
y la puse en 30. Por defecto, el método seno es ciclo entre menos
uno y más uno. Si multiplico ese valor
por esta curva punteada, aumentamos ese rango. Y este es el resultado. Quiero líneas suaves, así que elimino esta
parte del código aquí. Trate de usar
un valor diferente para la curva. Si necesitas más claridad sobre cómo este valor afecta el
movimiento de nuestras líneas. Y si quisiera
curvar para comenzar en un valor muy pequeño y
poco a poco aumentar, la curva
inicial será 0.1. Y Vc, la velocidad a la
que estará cada vez más
será de 0.25. Dentro del método de actualización para
cada fotograma de animación, quería aumentar
la curva por VC así. Y cuando las líneas se reinician, quiero que el ángulo y la
curva vuelvan a cero. Efecto interesante. Podemos hacer tantas
cosas diferentes con él ahora.
17. efecto de garabatas en el caos: Y si también aumentara la coordenada y
vertical por seno de la curva de tiempos de
ángulo, obtenemos este extraño movimiento de
ida y vuelta. Pero si uso coseno en lugar
de seno y coseno, trabajaremos juntos para mapear
un camino a lo largo de un
radio de círculo. Y debido a que la curva va
aumentando a medida que se ejecuta la animación, no
obtenemos Circle. De hecho, obtenemos espirales. Dije VC, velocidad de curva
a un valor mucho menor. Ahora estamos dibujando
espirales así. También puedo hacer que sea un
valor aleatorio entre -0.2 y más 0.2 menos los valores se moverán en la dirección
opuesta. A lo mejor también quiero aleatorizar qué tan rápido aumenta el ángulo. Va, La velocidad del ángulo
será un valor aleatorio entre -0.25 y más 0.25. Entonces lo uso aquí en lugar
del valor codificado duro. La velocidad a la que aumenta el
ángulo afectará qué tan
compacta es la curva, qué tan rápido se extiende. Esto es simetría. Quiero agregar un poco de caos ahora
para este sencillo proyecto de arte, o imaginar que alguien está dibujando estas hermosas espirales
simétricas. Pero en cierto punto
se enojan y
empiezan a garabatear al azar y rompen la forma de espiral. Digamos que si el temporizador es
más de la mitad de la vida útil, la segunda mitad del ciclo de
vida de las líneas comienza a multiplicar
va por menos uno, cambiándolo al valor
opuesto cada vez que toma un nuevo
fotograma de animación, cada vez que se dibuja un nuevo
segmento. Esto romperá la
espiral con esta forma. Tenemos un camino que comienza como una espiral y luego
se convierte en una línea discontinua. Yo quería que la línea estuviera
cada vez más rota. Necesitamos más caos
al final. Sí. Cambiemos esto a 0.9. La mayoría de las veces
será simetría. El último 10% será un caos
porque estamos modificando valor
va y no lo estamos trayendo de vuelta a
su gama original. Las líneas dejan de hacer espirales
como deberían. A medida que las líneas se restablecen, necesitamos ser también
reseteados y el valor va. Copio la línea 48 y la pego aquí
abajo dentro
del método de reset. Bonito. Empezamos con la
simetría y terminamos en el caos. Exactamente como yo
un sábado por la noche. Constantemente estamos
calculando
tiempos de vida 0.9 porque
este cálculo ocurre muy a menudo para
facilitar que JavaScript ejecute este código y ayude
un poco al rendimiento. Podemos precalcular esto solo una vez en el constructor de
clase, y luego usaremos ese valor
precalculado aquí. Lo llamaré e.g Este punto de ruptura de punto y
será tiempos de vida útil 0.85. Entonces puedo usar este
punto de ruptura aquí. Y en lugar de
calcular esto 60 veces por segundo para cada objeto de
línea, ahora, solo lo
estamos calculando una vez para cada línea en el punto donde cada objeto de línea se crea usando el constructor de
clase. Hago las líneas más anchas. Dije lienzo de
fondo a negro. Sí, este es el
efecto que quería. Comento el
estilo de trazo en la línea 54. Ahora el trazo es negro
así que no vemos nada. Se lo puedo dar al color blanco. Ahora podemos volver a ver
cómo las sombras
le dan un efecto 3D muy sutil. Dije número de líneas, 250. Ten cuidado aquí. Puede ser demasiado para computadoras más
antiguas y es
posible que obtenga un FPS más bajo. Yo hago 100, ahora solo estoy
experimentando. Puedo establecer el estilo de trazo
al degradado lineal que
definimos en la línea 15 solo para
ver cómo se ve eso. ¿Qué tal si uso gradiente radial? Para este,
definitivamente debería elegir diferentes colores para
que se vea bien. También puedo volver a usar el patrón de imagen
aquí. Interesante. ¿Has visto este gran método de
patrón que se usa antes o
es tu primera vez? Ahora tienes todas las
herramientas que necesitas para crear campos de flujo completamente animados y
hermosos, echa un vistazo a los enlaces en la
descripción y únete a mí en una clase avanzada donde
utilizamos las técnicas que
aprendimos hoy para crear arte
más generativo.
18. ¿Qué es un campo de flujo: Aquí hay una cuadrícula de ángulos. También podemos llamarlo campo
vectorial si agregamos sistema de
partículas encima de él y hacemos que las partículas
fluyan sobre la cuadrícula. Su movimiento está influenciado
por el vector de campo. La dirección y
velocidad de movimiento estarán influenciadas
por el valor del ángulo almacenado en la celda sobre la que se mueve
actualmente
cada partícula. Esta clase es para
personas creativas que quieren
entender cómo
funciona el código bajo el capó. No olvides consultar
la sección de recursos para descargar el código fuente si
quieres compararlo con el mío. Incluí múltiples descargas de código
fuente en puntos clave
del proyecto a medida que
avanzamos con la clase
en caso de que quieras
inspeccionar mi código y
compararlo con el tuyo. Creé una página web genérica con elemento HTML canvas en ella. Vinculé a los archivos style.css
y script.js. Yo hice un reinicio global de CSS y le di al elemento canvas
un fondo negro.
19. Configuración de lienzo HTML: Después de una sencilla configuración de HTML
y CSS, todo lo demás en el
proyecto será manejado por JavaScript aquí dentro del archivo
script.js. Como siempre, necesito configurar mi Canvas variable personalizada llamada cannabis
será documento, get element by ID e ID
I gave it was canvas one. El contexto ctx es ese lienzo
variable punto getContext. Y lo paso a la para crear una instancia de canvas
rendering context object. Ahora, el CTX contiene
todo integrado en los métodos de dibujo
y propiedades que cualquier navegador web
puede entender. Quiero que hoy tengas un efecto a
pantalla completa. Así que el ancho será ventana en un rave y la altura del lienzo
es ventana en su altura. No estoy seguro si lo puedes ver,
pero al hacer esto le dio a mi página
web barras de desplazamiento. No los quiero tan fácil
arreglar es darle a la lona elemento posición absoluta,
así, bonito. Entonces toda esta zona negra es nuestro Lienzo, nuestro tablero de dibujo. Puedo usar la variable ctx de la herramienta de
línea para dibujar algo. Ahora, si me consola puerta, podemos ver los ajustes por defecto. Por ejemplo, I. Podemos ver que el tipo predeterminado
de como FillStyle es negro para asegurarnos de que las formas dibujamos nuestras visibles contra el fondo
negro. Dije FillStyle a blanco.
20. Dibujo en forma en lienzo: Aquí abajo podemos ver todos los métodos de
dibujo de Canvas incorporados, por ejemplo ,
el método de arco,
que se puede usar para crear un arco o un círculo completo. Si tuviéramos más formas en Canvas, tendré que llamar a comenzar camino. Pero ahora puedo saltarlo. Y digamos que quiero un
círculo con un punto central en las coordenadas 100 horizontalmente desde el borde izquierdo de Canvas, 100 verticalmente
desde el borde superior. El radio del círculo
será de 50 píxeles. El ángulo de inicio del
arco será de 0 rad. Y como quiero
dibujar un círculo completo, el ángulo final será
math.pi por dos, que es aproximadamente
6.28 rad o 360 grados. Círculo completo. El método Arc
funciona con un camino, por lo que no
renderiza directamente nada en el cannabis. Simplemente posicionó
un camino invisible. Podemos elegir trazar ese trazado o rellenar
esa forma con color. Entonces llamo método de
relleno incorporado como este. Puedo mover el
punto central del círculo alrededor. Puedo cambiar el radio. Incluso puedo cambiar el ángulo final
o el ángulo de inicio para obtener
una forma diferente. Bien, entonces nuestro Canvas está
configurado y lo probamos
dibujando una forma. En esta área, mantendré mi configuración global de Canvas
para mantener nuestro código organizado. Hoy en día, estamos construyendo campo de flujo
animado. Se hará a partir
de líneas individuales. Entonces, ¿cómo dibujamos una línea
simple en Canvas? Comenzamos por Colin, incorporado y comenzamos el método path. Esto iniciará un nuevo camino
así como vestirá todos los caminos
anteriores. Si hay alguno,
llamamos movido al método para establecer las
coordenadas x e y de inicio de la línea. Llamamos a una línea a método para
establecer el final en coordenadas. O podemos encadenar
múltiples líneas a, para crear una forma más compleja, que es lo que
vamos a estar haciendo hoy. Igual que el método del arco. Mover a la línea final dos
métodos que acabamos de decir anteriormente. No renderizan directamente
nada en Canvas. Ahora tenemos que elegir
si queremos trazar el trazado o si queremos
rellenar esa forma con color, llamaré
método de trazo incorporado para dibujar el trazado. estilo de trazo predeterminado es negro, por lo que no es visible contra
el fondo negro. Voy hasta aquí y le dije estilo
trazo al blanco. Ahora podemos ver que estamos dibujando una línea a partir de las coordenadas 100, 202, coordenadas 400, 500. Por defecto, la línea
tiene un píxel de ancho. Puedo usar la
propiedad de ancho de línea para
establecerla en diez píxeles o 100. También puedo usar la brecha de línea
y configurarla para redondear, p. ej.
21. Programación orientada a objetos en JavaScript: Bien, Así es como dibujamos y
diseñamos líneas sobre lienzo HTML. Esto es todo lo que necesitamos saber para crear una amplia
variedad de efectos. Quería crear
muchas líneas animadas que fluirán
alrededor de nuestro Canvas. Voy a usar la
clase JavaScript llamada particle. Así. Cada partícula
se moverá y conectaremos sus
posiciones con una línea. Las clases de Javascript
son blueprints para crear muchos objetos similares. Y estamos a punto de construir un llamado sistema de partículas
hecho de muchas partículas. También voy a tener una
clase llamada efecto. Esto podría haber sido solo
un objeto simple porque solo
tendremos una
instancia de esta clase. Será el
cerebro principal de nuestra base de código. Entonces tenemos clase de partículas, un blueprint que
usaremos siempre que
necesitemos crear un nuevo objeto de
partícula. Y tendremos clase de efecto que manejará todo
el efecto, todas las partículas a la vez. Estoy usando clases y programación
orientada a objetos
para mantener nuestro código limpio, bien organizado
y fácil de leer. Este es un tutorial
para principiantes, así que quiero
que todo esté limpio y lo más fácil de
entender posible. Es mi principal objetivo. clase de afecto deberá estar al tanto del espacio disponible en el
cannabis. Entonces el constructor
esperará que width y height vengan como argumentos desde el exterior cuando se
crea una
instancia de esta clase usando la
nueva palabra clave dentro, convertí estos argumentos
en propiedades de clase. Tome con pasado como argumento aquí y conviértelo a
propiedad width en esta instancia de affect class, mismo para height. La clase de efecto tendrá método
inicializado. Este método se ejecutará solo
una vez para configurarlo todo. Tendremos esta propiedad de
partículas de perro. Esta será una matriz que contiene todos los objetos de
partículas actualmente activos. Entonces, cuando inicializamos
este efecto, queremos tomar
esta
matriz de partículas de carga y queremos usar método de empuje de matriz
incorporado para empujar una nueva partícula en la matriz. Esa partícula se creará usando la clase que
definimos en la línea 11. Entonces escribamos esa clase
de partículas ahora mismo. Cada partícula
también necesitará ser consciente del ancho
y alto del lienzo porque necesita saber cuándo se mueve
fuera del área del lienzo para mantener nuestro código modular en lugar del tamaño de lienzo
booleano
de las líneas 3.4, tomaré ese valor de
la clase de efecto principal. Quería acceder a estos
inmuebles desde las líneas 920. Voy a dar
acceso a la clase de partículas a toda la clase de
efectos. constructor de clase de partículas
esperará efecto como argumento y en su interior lo
convertiremos en una propiedad de
clase. Entonces aquí estamos apuntando hacia
el objeto principal del efecto. Tenga en cuenta que los objetos en JavaScript son llamados para hacer
referencia a los tipos de datos. No estamos creando una
copia del objeto efecto. Cada vez que creamos
una nueva partícula, solo
estamos apuntando a ese
mismo espacio en la memoria que contiene la clase de efecto de
todos los objetos de partículas. De esa manera, las partículas
tienen acceso a todos los métodos y propiedades
en el vidrio de efecto principal. Y también si alguna de
estas propiedades actualiza porque solo estamos
apuntando a ese objeto, cualquier cambio en el objeto
efecto será inmediatamente visible desde
los objetos de partículas, lo que nos será muy
útil hoy en día. Como dije antes, vamos a tener un efecto
objeto para gestionar todo. Y vamos a tener muchas partículas, cientos o tal vez miles. Veamos cómo va. Cada partícula tendrá coordenada x e y
inicial. coordenada x horizontal
será un valor aleatorio entre cero y este efecto de punto
a partir de la línea 13 ancho de punto, estamos accediendo a esta
propiedad desde la línea 20. coordenada y vertical
será un valor aleatorio entre cero y esta altura de
punto con efecto de punto. Para evitar valores de subpíxeles, es una buena práctica
usar enteros, números
enteros sin puntos
decimales envolviéndolo en Math.floor, esto redondeará el valor al entero inferior más cercano. Cada partícula tendrá
un método de sorteo público. Este método esperará
contextos como argumento para especificar en qué tipo de
nosotros queríamos basarnos. Lo paso como un argumento como
este para mantener nuestro código más modular y menos
dependiente del entorno exterior. Entonces tomamos ese contexto y
llamamos método de
rectángulo de relleno incorporado. El método de relleno de rectángulo
es muy sencillo. Simplemente tomará
estas coordenadas X e Y aleatorias
que acabamos de definir, y ahí dibujará un
rectángulo. Su ancho y
alto serán, por ejemplo, diez veces diez píxeles. Tenemos nuestra clase de partículas
y tenemos clase de afecto. Quería crear una
instancia de clase de efecto. Creo una
variable personalizada que llamo por ejemplo efecto, y será igual
a un nuevo efecto como este. La nueva palabra clave
buscará clase con ese nombre. Lo encuentra aquí arriba y
activará su
constructor de clase en línea 23. Podemos ver que efecto espera ancho y
alto como argumentos. Entonces lo pasamos
ancho de lona desde la línea tres. Y algo así como la altura de
la línea cuatro, así. Ahora, puedo tomar que
afecte a la variable y llamar al método init que
definimos en la línea 28. El método Init tomará la matriz de
partículas y
empujará un nuevo
objeto de partícula en la matriz. Obtenemos un error porque
aquí en la línea 12, se
puede ver que el constructor de
clase de partículas espera una referencia a la clase de
efecto principal como argumento, luego usa esa
referencia para acceder a las propiedades
width y height de Canvas. Ya que estamos creando
esa partícula dentro de la propia clase de efecto, le paso esta palabra clave, que en esta área se refiere
a toda la clase de efecto. Bonito. Entonces, después de que creamos una
instancia de vidrio de efecto, y después de que llamemos a
este método init, espero que la
matriz de partículas de la línea 26 contenga un objeto de partícula. Consola registro el cristal de
efecto a comprobar. Puedo ver el objeto efecto. Tiene propiedades de anchura y
altura. Y si abro esta matriz de
partículas, puedo ver que hay un objeto de
partícula dentro. Compruebo si todas
las propiedades tienen valores. Si veo indefinido
o no en alguna parte
, indicaría un
problema. Todo está bien aquí. Ahora, necesito una manera de
dibujar realmente mi efecto en Canvas. Le daré otro
método al que llamo, por ejemplo, render dentro de nuestro ciclo sobre todos los objetos de partículas
dentro usando
array
para cada método. Por ahora sabemos que solo hay
un objeto de partícula en su interior. Para cada objeto de partícula
dentro de la matriz de partículas, llamo a su método de
retirada asociado. Definimos ese
método de dibujo en la línea 17 y podemos ver que espera
contexto como argumento. Entonces tomo método render y lo
llamo necesitamos este contexto. Entonces tomo CTX de la línea dos. Lo paso para renderizar. Dentro del render se
esperará como contexto. Y pasamos esa
referencia de contexto para dibujar método porque sabemos que
se espera en la línea 17. A partir de ahí, se
llama al método del
rectángulo de relleno y
se dibuja nuestra partícula. Bonito. Puedo cambiar el ancho y altura cuando actualizo
la ventana del navegador, coordenadas
x e y de las líneas 14.15 se aleatorizan
y se dibujan partículas.
22. Dibujo de sistemas de partículas: La clase de efecto principal creo una propiedad que llamo
número de partículas. El método inicializado se ejecutará, solo quiere configurar nuestro
efecto dentro. Voy a crear estas
50 partículas. Puedo hacer eso
usando un bucle for. Se ejecutará 50 veces, y cada vez que se ejecute, tomará matriz de partículas, y empujará una
nueva partícula con coordenadas x e y
aleatorias dentro. Y así es como se crea
un sistema de partículas simple. Si lo deseas, puedes guardar
este código como un boilerplate en una carpeta diferente
porque puedes usarlo para tantos experimentos
diferentes, afectos y obras de arte
generativas. Estoy llamando al método init desde
aquí en la primera carga de la página. También puedo eliminar
este código y lo llamo this.in desde dentro del constructor de clase de
efecto. Porque cuando creamos una
instancia de una clase usando la nueva palabra clave
constructor se ejecutará todo el código en el
blueprint línea por línea. Podemos aprovechar ese comportamiento poniendo aquí
cualquier código que
queramos ejecutar en el
mismo punto cuando se crea
una instancia de esta
clase.
23. Animación de sistemas de partículas: Estamos construyendo un campo de flujo. Quiero que estas partículas
se muevan y dejen
líneas de senderos detrás de ellas. Animemos esta velocidad X la velocidad
horizontal será una. Las partículas se
moverán un píxel por fotograma de
animación en la dirección
positiva. En el eje x horizontal, se moverán hacia la derecha. Velocidad. Y también será un píxel
por fotograma. La dirección positiva en el eje y
vertical significa hacia abajo. Dado que ambas
fuerzas se
aplicarán a la partícula
al mismo tiempo, esperaba que las
partículas se movieran hacia la esquina inferior
derecha de Canvas. A ver. El movimiento se manejará
dentro del método de actualización. Este método definirá un
solo paso en la animación. Y cuando llamamos a este
método de actualización 62 veces por segundo, creará una
ilusión de movimiento. Por cada fotograma de animación, quiero aumentar la posición
x horizontal de esta partícula desde la línea 14 por el valor de velocidad
x desde la línea 16. También quiero aumentar la posición vertical
por velocidad. ¿Por qué? Aquí dentro de render, a medida
que recorremos todas las partículas, activamos ahí método
draw y
también llamamos al
método update que acabamos de escribir. Esto se llama, solo quiere
así que no hay movimiento. Y va a llamar a este
método de render una y otra vez. Quería dibujar partículas,
actualizar sus posiciones, volver a
dibujarlas en esas posiciones
actualizadas, actualizarlas nuevamente,
dibujarlas nuevamente, y así sucesivamente. Llamando a esto una y otra vez, crearemos animación,
una ilusión de movimiento. Necesitamos bucle de animación. Creo una
función personalizada a la que llamo, por ejemplo animar desde dentro de nuestra llamada render para dibujar y
actualizar todas las partículas. Y luego llamo incorporado Request Animation
Frame y método. Lo paso, animo el nombre
de su función padre. Así animate runs, render se
llama particles are drawn and updated and then request animation frame
and method calls animate. Nuevamente, tenemos un método
de marco de
animación de solicitud de bucle diseñado para este propósito, y tiene características especiales
como todo para generar
las etiquetas de tiempo para nosotros. Y también se ajusta
a la frecuencia de actualización de la pantalla. Tengo una pantalla normal, así que mis animaciones funcionan a
60 fotogramas por segundo. Si tienes un juego y una pantalla de alta
frecuencia de actualización, tus animaciones se ejecutarán más rápido. Puede usar fácilmente el marco de
animación de solicitud y su marca de tiempo
generada automáticamente para establecer velocidad de animación que desee. Ahora todo está
listo y puedo llamar animar nuestras esperadas todas las partículas para
mover un píxel a la derecha y un píxel allá
abajo marco de animación. Están dejando senderos
porque podemos ver pintura
vieja, sus posiciones
anteriores. Si quería ver solo el fotograma de animación
actual, necesito eliminar Canvas entre cada fotograma usando el método de
rectángulo claro. Quiero borrar todo el
lienzo desde las coordenadas cero-cero hasta el
ancho del lienzo, la altura del lienzo. Bonito. Estamos animando. Cambio de velocidades. La relación entre
velocidad x y velocidad. ¿Por qué? Definiremos la dirección
y velocidad del movimiento. También podemos aleatorizar la
velocidad de cada partícula. ¿Qué tal un
valor aleatorio entre -2.5 y más 2.5 menos el valor
se moverá hacia la izquierda, más los valores a la derecha En el eje vertical, los valores
negativos
moverán las partículas hacia arriba. Los valores positivos
moverán las partículas hacia abajo. La relación entre la
velocidad x aleatoria y la velocidad. ¿Por qué determinará la
dirección final del movimiento? Y ahora las partículas se mueven en
todas las direcciones posibles. Puedo hacer las
partículas más pequeñas.
24. Líneas y senderos para dibujar: En realidad quiero dibujar líneas. Yo llamo método Big Bath para decirle a JavaScript que
quería iniciar un nuevo camino. A medida que la partícula se mueve alrededor Canvas para cada fotograma de animación, actualizará su posición
x e y. Y haré un seguimiento
de esas posiciones como objetos
simples con
propiedades x e y dentro
del array history. Al principio, a cada partícula se le
asignará una posición x e y aleatoria
en algún lugar dentro del área del lienzo. Y usamos estos valores
como el primer objeto, el primer elemento
con un índice de cero dentro del array history. El punto de inicio de la línea
se guardará por el método move to. Queremos comenzar desde las
coordenadas x e y
del primer objeto dentro del
objeto array history con un índice de cero. Luego creamos un bucle for. Se ejecutará siempre y cuando
haya más elementos en
la matriz de historia. Por cada objeto, todos estos
objetos se ven así. Para cada objeto de posición
dentro de la matriz de historia, tomaremos las
coordenadas x e y de un
objeto en ese índice. A medida que los ciclos de bucle for
sobre la matriz, pasamos sus coordenadas x e y
a la línea dos métodos. Entonces punto de inicio de la línea. Después recorremos
todas las posiciones dentro la matriz de historia y las
conectamos con una línea. Entonces recorremos ese camino para dibujarlo
realmente en Canvas. Ahora necesito asegurarme de que se agreguen
posiciones a la matriz de historia a medida que la
partícula viaja alrededor. Cada vez que actualizamos la posición de las
partículas, tomamos esta
matriz de historial de puntos y empujamos un objeto como este con estos valores
x e y actualizados dentro. Bonito, Parece que es
solo una línea recta, pero en realidad es una forma
hecha de muchos segmentos de
línea más pequeños. Puedo, por ejemplo, hacer que se
mueva agregando un valor aleatorio entre
-1.5 y más 1.5. Esto debería dejar
más claro visualmente que estas líneas están
hechas de segmentos. Puedo hacer
lo mismo verticalmente. Puedo aumentar el rango
aleatorio puede ser de -2.5 a más 2.5. Puedo aumentar aún más el
rango. Un valor aleatorio entre
-7.5 y más 7.5. Por último, esto empieza
a parecer interesante. ¿Correcto? Ahora. Estos son simplemente crecer
sin cesar en líneas. ¿Y si quiero definir la longitud
máxima de una línea? En este caso, esto significará el número
máximo de segmentos. Dentro del método de actualización. Digo que si la longitud de la matriz de historia es
mayor que maxlength, llame al método de
desplazamiento de matriz incorporado. Así que tenemos dos métodos
de matriz aquí. El método Push agrega un nuevo elemento
al final de una matriz. El método Shift elimina un
elemento desde el principio. Porque estamos
agregando nuevos elementos al final de la matriz. El método Shift elimina
el segmento más antiguo. Entonces las aerolíneas se
arrastran así. Pueden parecer pequeñas
criaturas bajo el microscopio. Podría simplemente darles algo de
IA y convertir esto en un juego. Puedo aumentar la longitud máxima de
la línea a 100s segmentos. O puedo hacer un
valor aleatorio 10-110. Ahora, algunos de ellos tienen colas cortas y otras muy largas.
25. Patrones de movimiento con trigonometría: También puedo aplicar trigonometría, que partícula tendrá
propiedad angulada que
inicialmente comenzará en cero. Por cada fotograma de animación, aumentaré el ángulo
en algún valor pequeño. El valor del ángulo está en radianes. Entonces puedo pasar ese
ángulo cada vez mayor al signo de Martha, que automáticamente mapeará estos valores a lo largo de una onda sinusoidal. Esto le dará a la
coordenada horizontal una emoción
de onda irregular. Mira lo que pasa
cuando hago esto para la posición vertical también. En lugar de agregar aquí, intento y multiplicar. Lo hago tanto por combinación
de seno como de coseno. Mapearemos las posiciones a lo largo
del radio de un círculo, multiplicándolo por un valor como este aumentará el radio. Puedes intentar usar diferentes
combinaciones de valores y aplicar distintas operaciones
si quieres experimentar, hay muchas cosas
que se pueden hacer aquí. Básicamente, construimos
un sistema de partículas donde cada partícula
dibuja una línea detrás de ella. Comento una línea
69 por un tiempo.
26. Creación de un campo de vector: Ahora mi objetivo es hacer que estas líneas viajen
alrededor del lienzo siguiendo un orden específico para
crear un efecto de campo de flujo. El campo de flujo se basa
alrededor de una cuadrícula de ángulos. Cada celda de la cuadrícula
almacena y el valor del ángulo. Y cada celda en esta cuadrícula en el campo de flujo tiene una relación con
sus celdas vecinas. No son al azar. Aumentan o
disminuyen gradualmente. Y a medida que la partícula viaja
sobre la cuadrícula, celda por celda, velocidad de
partícula y dirección de movimiento se ve influenciada
por estos valores de ángulo, creando un patrón de movimiento. Algoritmo muy común
para generar valores de
ángulo para un
campo de flujo es el ruido de Perlin. Crea un ruido de gradiente que cambia
gradualmente
los valores de manera aleatoria. El efecto resultante se ve muy natural y puede ser
utilizado para generar texturas para serina
generada por o muchas otras cosas. Hoy generaremos
un campo de flujo espiral donde usaremos valores de
seno y coseno y los adjuntamos a coordenadas
verticales y
horizontales de cada punto de cada celda. Esto crea un hermoso patrón repetitivo
simétrico. Seremos capaces de
acercar y alejar el patrón para resultados muy
diferentes y. Vamos a tomarlo
paso a paso y
quedará claro de lo que estoy
hablando a medida que lo construimos. Nuestro objetivo ahora es
crear una cuadrícula que divida todo el lienzo
en celdas individuales. Digamos que quiero vender el tamaño cada celda para que sea 20
veces 20 pixeles. Esto dividirá el lienzo
en filas y columnas. El número de filas y columnas
dependerá del ancho y alto de Canvas
y de este tamaño de celda. Podría calcular aquí el número
de filas y columnas. Pero como quiero que este
efecto sea sensible,
voy a calcular ese método de init
interior. Entonces podemos llamar a ese
método init cada vez que
ocurre un evento de redimensionamiento para recalcular correctamente toda
la cuadrícula de campo de flujo. Este campo de flujo de carga
será una matriz que contiene valores de
ángulo para
celdas individuales en la cuadrícula. El número de filas
será la altura del área del lienzo dividida
por el tamaño de celda. El número de columnas se dividirá por
onda por tamaño de celda. También estableceremos el
campo de flujo en una matriz vacía en
caso de que se
llame a este método init al cambiar el tamaño de Canvas. De esa manera, se
eliminarán todos los valores
antiguos y podremos
recalcular los nuevos valores. Ahora, quiero viajar sobre esa cuadrícula siempre que haya
un gran involucrado, la forma más fácil de manejarlo es con dos bucles for anidados, el bucle for externo, el ciclo sobre la cuadrícula, fila por fila desde la fila cero, siempre y cuando
haya más filas. El bucle for interno viajará sobre cada fila de
izquierda a derecha. Entonces entramos en el bucle exterior, estamos en la fila cero. Entramos en el bucle interno
y circulamos por las celdas de esa
fila una por una. Llegamos al final, salimos del bucle interno. Entramos en el bucle exterior, Y aumenta, e
ingresamos a la siguiente fila. Otra vez. Pasamos en ciclo por todas las posiciones de
esa fila una por una. Repetimos este
proceso fila por fila hasta cubrir
todo el Lienzo. Cada vez que ingresamos a una nueva celda, creamos un valor de ángulo. Aquí podemos hacer diferentes cosas. Simplemente ataré las coordenadas x e
y al seno y al coseno y al coseno para
crear un patrón en espiral. Sabemos que si
pasamos un aumento en el valor del ángulo a
seno o coseno, estos métodos mapearán este aumento de
valores a lo largo de una onda. En este caso, esos valores
crecientes son las posiciones
x e y de
las celdas en la cuadrícula. Entonces a medida que nos movemos a lo largo de la cuadrícula, creamos espirales y curvas. Cada vez que generamos
un nuevo valor de ángulo, lo
empujamos a la matriz
de campo de flujo. tener en cuenta que
estamos ciclando, integramos fila por fila,
generando estos valores, pero
los estamos almacenando en una matriz como una única
secuencia continua de valores. Debemos tener esto en
cuenta cuando necesitamos extraer de nuevo estos valores de ángulo, para que coincidan correctamente con posición actual
x e y de
las partículas. Entonces, en este punto, la matriz de campos de
flujo debe llenarse
con valores de ángulo. Así que vamos a registrarlo en consola. En realidad estoy
en el registro de consola después de cada fila, debería haber puesto
el registro de la consola aquí después de que todo esté hecho,
pero no importa. Podemos ver que se están generando
valores de ángulo. Perfecto. Entonces giramos
sobre el lienzo, integramos, y para cada
celda en esa cuadrícula, generamos valor de ángulo y
comenzamos todos estos valores de ángulo
dentro de la matriz de campo de flujo. Debido a que pasamos este aumento
gradual en los valores
x e y a
seno y coseno, creamos un hermoso patrón
simétrico. El patrón se
revelará cuando
dibujemos el campo de flujo.
Entonces hagámoslo. Ya tenemos
partículas que se mueven sobre Canvas y arrastran
líneas detrás de ellas. Actualmente, estamos usando
esta lógica para moverlos. Alejemos todo esto
y cambiemos completamente este código en el
método de actualización aquí quiero que las partículas se muevan y la dirección de
su movimiento
dependerá de la posición
de la partícula medida que viaja sobre diferentes
celdas en el campo de flujo. Los valores de ángulo en el
campo de flujo cambian celda por celda. Y este ángulo
determinará el movimiento de la partícula que actualmente
fluye sobre esa celda. Hay muchas
formas diferentes de hacer esto. Voy a crear una variable auxiliar
temporal x, y será
igual a la exposición
actual de partículas dividida por tamaño de celda. Básicamente, estoy diciendo
cuántas celdas hay en nuestra cuadrícula desde el borde
izquierdo de Canvas, esta partícula actualmente está, en qué columna
estamos actualmente. Recuerda que el
tamaño de celda se fijó en 20. Quiero enteros aquí, así redondearé el valor a la baja. variable y auxiliar
será la posición
actual de las partículas y
dividida por el tamaño de la celda. ¿Cuántas células? Desde arriba
estamos en qué fila. Ahora puedo usar estos valores
para mapear las coordenadas x e y de una partícula a un índice
en la matriz de campos de flujo. Básicamente tengo una partícula
con cierta posición x e y en una cuadrícula
bidimensional. Y tengo una matriz que
representa esa cuadrícula, pero es solo un
largo conjunto de números. Entonces, lo que estoy
tratando de hacer ahora es mapear esa posición x e y a ese índice para poder extraer
el valor de ángulo correcto. La rejilla de nanopartículas actual posición vertical y
horizontal. Y sé sobre
qué columna y fila en la cuadrícula de campo de flujo
se está moviendo actualmente. Ahora necesito usar este valor de
columna y fila para obtener
el valor de ángulo de la celda de la matriz
de campo de flujo. Esto es un poco complicado visualizar si eres principiante, así que no te preocupes
demasiado para obtener índice de disposición de matriz llena
de fluido, tomo el número de fila que
calculamos aquí, y lo multiplico
por el número de columnas que calcula
este bloque filas, términos, celdas por fila básicamente
necesita saber en qué celda
estamos actualmente
porque agregamos un valor de ángulo por celda
en matriz de campo de flujo. Entonces agregamos por
muchas celdas que estemos en la fila actual
en la cuadrícula así. Esto nos da índice dentro de la matriz de campo de
flujo que contiene el valor de ángulo de la celda sobre la que nos estamos moviendo
actualmente. Luego establecemos el valor
de ángulo de esta partícula al índice dentro de
la
matriz de campo de flujo que acabamos de calcular.
27. Cómo crear un campo de flujo: Ahora tenemos múltiples opciones
diferentes de
cómo usarlo para lograr
diferentes patrones. Voy a establecer la velocidad x dos coseno
del ángulo al principio. Velocidad y será el signo
del mismo valor que acabamos de
extraer en línea 35. Entonces tomo la posición
horizontal tamizada de partículas, y la aumento en
ese nuevo valor de velocidad. Y hago lo mismo para
la posición vertical, aumentándola por velocidad vertical. Elimino este código. Entonces nos cortamos en
una cuadrícula invisible. Cada celda tiene 20 veces 20 píxeles y tiene un valor de
ángulo específico. Calculamos qué
columna y qué fila de esta cuadrícula se mueve
actualmente la partícula. Mapeamos ese valor de columna y
fila para indexar en matriz de campo de
flujo para extraer valor de
ángulo que pertenece
a la celda que necesitamos, aumentamos la velocidad x por
coseno de esa velocidad de ángulo. ¿Por qué por señal? Esto nos dará una dirección de movimiento
dependiendo de ese ángulo. Después aumentamos las partículas en la posición
X e Y. Por estas velocidades. Empujamos esta nueva posición de
partículas dentro matrices de
historia para que
podamos animar su cola, la línea que cada
partícula droga sola. Si la longitud de la línea
es mayor que maxlength, eliminamos el segmento más antiguo. Yo descomentado render para
ver qué movimiento obtenemos. No lo parece, pero ya tenemos
un campo de flujo de trabajo con patrón de
espiral sinusoidal y coseno. Simplemente estamos alejados
muy lejos de él. Tendrá más sentido ya
que jugamos con el código ahora. Entonces la idea base es que analizando un
valor de ángulo cada vez mayor a seno y coseno, haremos que los valores circulen periódicamente entre
menos uno y más uno. Utilizamos las posiciones X e Y de cada partícula ya que éstas
aumentan en los valores de ángulo. Entonces el patrón estará atado
a las coordenadas de esa manera. Cierro esto entre paréntesis y
lo multiplico por dos. Esto aumentará el
radio de la curva. Elimino el rectángulo. Yo sólo quería líneas. Hago que la longitud máxima de la
línea sea un valor aleatorio, 10-210 segmentos. Puedo usar diferentes valores aquí. Aumentemos el número de partículas para que podamos ver
mejor el patrón. Mira lo que pasa si poco a poco
aumento este valor, 0.5. Puedo ir mucho más alto que esto. Pienso alrededor de las diez. Pongamos este valor
en variable, en una propiedad de clase. A esto lo llamo la curva punteada. Te voy a mostrar por qué lo llamo curva en un minuto.
Será claro. Yo uso esa propiedad aquí. ¿Bien? También puedo multiplicar
x e y por un valor. Si los valores son iguales, obtendremos un
zoom simétrico en ese patrón. Aún no es del todo obvio, pero de esto
surgirá un patrón claro. Tómate conmigo. Quiero que estos valores sean
idénticos para la simetría, y los pondré
en una propiedad de clase. A esto lo llamo Zoom. Dije esto el
Zoom al punto cero. Para tener en cuenta que curva Zoom también está conectada
al tamaño de celda debido a cómo atamos la curva sinusoidal
y coseno a una posición en un gran cambio en tamaño de
celda
afectará el patrón. Afectará al Zoom. Creo que en este punto
ya podemos llamarlo campo de flujo. Aumenta lentamente el
zoom para mostrarte cómo ese valor
afecta el patrón. Puedo
entrar realmente en el patrón, acercarme el zoom y despacio, lo alejo. Aún así. No creo que sea
obvio cuál es el patrón. Subamos aquí al constructor de clase de
partículas. Puedo eliminar estos
valores iniciales de velocidad x y velocidad. ¿Por qué? Porque se sobrescriben de inmediato aquí dentro
del método de actualización. Quiero que cada línea se mueva
a una velocidad diferente. Entonces voy a dar a cada partícula
una propiedad modificadora de velocidad, y será un entero
aleatorio 1-3. Aquí abajo, multiplico la
velocidad x y la velocidad. Por que por ese modificador de velocidad. Ahora algunas líneas se mueven
más despacio o más rápido. Aumentemos la velocidad. Modificar organizar. Para mostrarte claramente cómo la curva y el zoom
afectan el patrón. Necesitamos líneas para resetear cuando terminen su secuencia de animación. Creo un método al que llamo por ejemplo reset. Cuando el
reset dije x e y coordinan a una nueva posición
aleatoria en algún lugar alrededor del lienzo. Y también necesito
establecer el array histórico a estos nuevos valores como la posición inicial
con un índice de cero. este momento, la lista
interminable de movimientos más grandes en algún lugar
lejos de la pantalla. Voy a crear una
propiedad a la que llamo, por ejemplo, temporizador. Será la longitud máxima
de la línea por dos. Por cada tick de animación, disminuiré
el temporizador en uno. El temporizador comienza como un valor
igual a maxlength. Los términos a ello disminuyen en uno
por cada fotograma de animación. Siempre y cuando el temporizador sea
más o igual a uno, animaremos la línea y haremos
gatear como un polvo. Ya. Cuando el temporizador llegue a uno, las líneas se congelarán
en su lugar así. En este punto, queremos ejecute
una sentencia
else que
comenzará a eliminar un segmento antiguo de cada línea uno por uno, haciendo que la línea
desaparezca del final. Eso lo hago llamando a shift
en el array de historia. Esto nos dará
un error cuando
eliminemos todo
del array history, pero aun así intentamos dibujarlo. Por lo que sólo voy a ejecutar
esta declaración else. Si la matriz historia contiene
más de un elemento, sólo entonces eliminar todos los
segmentos de la línea. Las líneas fluyen alrededor. Cuando el temporizador llega a cero, comenzamos a eliminar todos los segmentos hasta que no queden
más segmentos. Perfecto. En ese punto, quiero que la línea se reinicie y vuelva a repetir este
ciclo de animación. Así que de lo contrario llamar a este método de restablecimiento de
puntos que acabamos de definir en la línea 56. Bien, no está funcionando porque
también necesito restablecer el temporizador
a su valor original. Enhorabuena,
construyes un campo de flujo. Esta es una base de código muy sólida y podemos hacer
tantas cosas con ella. Por fin es hora de usar
correctamente Curve y zoom para mostrarte el
patrón del que estaba hablando.
28. experimentos de campo de flujo: Como decíamos, el
ruido de Berlín creará un aspecto natural en el patrón de ruido
degradado. Estamos calculando valores de
ángulo para nuestro campo de flujo en línea
85 usando trigonometría. Entonces, aunque no lo
parezca, ahora, este es un patrón
matemático muy simétrico que se repite sin cesar
en todas las direcciones. Déjame mostrarte a lo que me refiero. Mira lo que pasa cuando
aumento el valor de curva. Disfruto mucho
viendo este efecto. Hay algo muy
relajado y sobre esto, creo que ahora se puede ver un poquito que tenemos
un patrón repetitivo. Cambio el zoom
y me
alejo de él para
ver claramente la repetición. También puedo acercarme
mucho
al patrón y solo
miramos la pequeña parte del mismo. Parece que el
flujo es en realidad aleatorio, pero sabemos que no lo es. Voy a incrementar el
número de partículas. Mi computadora puede manejar esto, pero debes
ajustar el número de partículas para asegurarte de que
tu computadora pueda animarlo sin problemas para que
no tengas que usar
2000 partículas aquí. Pruebe diferentes valores y vea. No recomiendo
ir mucho más 2000 a menos que tengas una computadora
muy potente. Los campos de flujo son
un efecto tan hermoso. Y ahora ya sabes cómo
construir uno tú mismo. Aquí solo estamos jugando con el patrón de seno
y coseno, pero podemos usar este
código para cambiar el flujo y hacer que siga
muchos patrones diferentes. Mira lo que pasa cuando
cambio la curva de valor. A medida que el valor aumenta, comenzará a emerger
un patrón en espiral. Esa rodilla va un poco más alta. Aquí comenzará a curvarse
en espiral. Y a medida que aumento el valor, se hace una espiral cada vez más. Creará
una especie de caracol en forma de caracol si vamos lo suficientemente altos. Ahora es cada vez más obvio. Y aún más, la curva
apenas se enrolla en espiral sobre sí misma. Interesante, ¿no? Entonces ahora creo que es muy
obvio cómo
afecta la curva a la forma espiral
del campo de flujo. Este patrón se repite
sin cesar en todas las direcciones
y podemos acercarlo y alejarlo
cambiando los valores que usamos como este
zoom de punto en la línea 75, puedo acercar mucho
al patrón. Y a medida que aumento este valor, lentamente
estamos alejando el zoom. En este punto podemos ver la naturaleza repetida
de este patrón. Como asumimos lo suficientemente lejos. Voy aún más lejos. Puedo hacerla espiral más. Ya ves como el patrón es
dentado y no muy liso. Esto es exponer la naturaleza
similar a una cuadrícula
del campo de flujo ya que el ángulo
solo cambia cada 20 píxeles, puedo reducir el tamaño de la celda para hacer que el flujo sea más suave. Y básicamente cortando
cannabis en trozos más pequeños, cinco por cinco píxeles. Como ahora podemos colocar más columnas en el área de lienzo disponible, cambio en el tamaño de
celda también se alejó muy
lejos del patrón. Ahora podemos ver claramente cómo
se repite sin cesar. No es aleatorio
como el ruido de Perlin. Es muy matemático
y simétrico. Acerco un poco más. Creo que está claro
cómo funciona esto. Ahora, siéntete libre de jugar con él y hacer tus propios experimentos.
29. Modo de grid y depuración: Ambos nodos son básicamente
una cuadrícula de ángulos. Visualicemos
esa cuadrícula para dejar claro cómo funciona exactamente. Vamos a crear un modo de depuración
en la clase de efecto principal, creo un método
al que llamo por ejemplo dibujar una cuadrícula. Esperará contextos como argumento dentro
creo un for-loop. Primero, dibujemos líneas
verticales, columnas. Esta
propiedad de llamadas de punto ya tiene un valor que representa el
número de columnas en la cuadrícula. Entonces lo usamos aquí. Cada vez que entramos en
una nueva columna, llamamos start path. Quería trazar
una línea vertical. Mover al método para definir las
coordenadas x e y iniciales de la línea. Cada línea comenzará en posición horizontal
dinámica, tamaño de
celda, el ancho de una sola celda multiplicado por el número de la columna en la
que nos encontramos actualmente. Todas las líneas verticales comenzarán en la parte superior desde la coordenada y cero. línea dos
determinará las coordenadas x
e y finales de nuestras líneas de cuadrícula. posición horizontal
volverá a ser tamaño de
celda multiplicado por el número de columna. Y quiero que las líneas terminen todo el camino en la parte inferior
del área del lienzo. Entonces esta altura de punto. Después acariciamos líneas. Veamos lo que tenemos hasta
ahora por Colin dibujar método
grid desde dentro
del método render. Bonito. Vemos líneas verticales que representan columnas
en nuestro campo de flujo. El tamaño de celda es de solo cinco, así vemos línea
cada cinco píxeles, cambio a un 30. Como puede ver, esto también afectó el zoom
en el patrón. A medida que aumenta el tamaño de las celdas, podemos caber menos celdas por fila, lo que significa que las espirales
creadas por
seno y coseno en línea 85 tienen
menos tiempo para desarrollarse. Todo es porque
ajustamos el valor del ángulo, pasamos al seno y al coseno
a los números de columna y fila, menos columnas, menor
rango de valores pasados como ángulo a seno
y coseno en línea 85, lo que afecta al patrón. Siempre puedo compensarlo
ajustando esta
propiedad de zoom en la línea 75. Bien, estamos dibujando líneas
verticales. Dibujemos también líneas
horizontales, las filas, para completar nuestra cuadrícula. Nuevamente, comenzamos por comenzar
camino comenzando las
coordenadas x e y de cada línea
horizontal serán cero horizontalmente. Entonces desde el borde izquierdo de
Canvas y verticalmente será el tamaño de celda
multiplicado por el número de fila. El punto final de cada línea
será el borde derecho de Canvas. Por lo que este ancho de punto horizontal, punto final
vertical será de nuevo tamaño de
celda veces el número de fila. Yo acaricio las líneas. Perfecto. Ahora podemos ver la grilla completa. Mira de cerca las líneas. ¿Ves cómo el valor del ángulo, la dirección de
la línea cambia en
los puntos a medida que las líneas ingresan
nuevas celdas en la cuadrícula Cada celda en el campo de flujo tiene asignado un valor de ángulo
diferente, y las líneas siguen esos ángulos para darles dirección
de movimiento. Este visual debería ayudarte a entender cómo funcionan más bien
los campos de flujo. Y si estás codificando, puedes inspeccionarlo
de cerca en tu computadora y
ver realmente lo que está sucediendo. Cambiar el valor
del tamaño de celda, dos, número
aún mayor, y el misterio de hacer
campos de flujo debe ser resuelto. Quería que las
líneas de la rejilla fueran más delgadas, pero no quiero que este cambio afecte el ancho
de línea de las líneas que fluyen. Por esa razón, envolveré todo
este bloque de código
entre safe y restore. Estos dos métodos de
Canvas incorporados, asegúrese de que cualquier
cambio que hagamos a un estado se mantendrá limitado
a un área específica. Esos cambios pueden incluir
cualquier tipo de configuración como FillStyle, estilo de
trazo, ancho de línea, opacidad, alfa global, así como cosas
como
rotación y escalado, que no estamos usando hoy en día. Si querías saber cómo usar
rotar y escalar, puedes consultar mi
clase sobre fructosa. Si configuro el
estilo de trazo para escribir, solo
afectará el grado, no las líneas que fluyen, no el sistema de partículas. El método Save crea
un punto seguro, como en un videojuego, podemos hacer los cambios que
queramos aquí, por ejemplo, ancho de línea, solo 0.3 píxeles. Estos cambios afectarán este código de dibujo
y luego restaurarán. Reiniciaremos todos los
cambios realizados aquí hasta el punto en que fue
cuando lo llamamos seguro. Debido a eso, cuando
luego dibujamos las líneas fluidas, el sistema de partículas usando método de
dibujo en la clase de
partícula, no se verán afectadas por este estilo de trazo y
este ancho de línea en absoluto. Quería mantener la
grilla en nuestro proyecto, pero quiero una forma
para que el usuario
pueda ocultarla y
mostrarla fácilmente. Creo una propiedad de
modo de depuración llamada este punto d back se
establecerá en true inicialmente, igual que lo hicimos con
Colin en ella aquí. Cuando
se instancie la clase de efecto, se ejecutará
todo el código dentro del
constructor. De hecho, puedo poner cualquier
código que quiera aquí, incluso un oyente de eventos, cuando creamos una instancia de clase de efecto usando
la nueva palabra clave, en ese punto, quiero se aplique
un oyente de eventos para el evento key
down. Necesito asegurarme de que todavía
tengo acceso a las propiedades en el constructor de
clases, específicamente esta propiedad
de depuración desde el interior de este oyente de
eventos. Si usas una función de
devolución de llamada regular, tendrás que vincularla. Alternativamente, puedo
usar la función de flecha ES6. Estas funciones heredan
automáticamente el ensartado de
su ámbito padre. Entonces, incluso cuando este
oyente de eventos se ejecute más tarde, aún
podrá
recordar que originalmente se definió aquí, y podrá controlar esta propiedad de depuración de puntos para nosotros. Si usa la función de
devolución de llamada regular aquí, obtendrá un error porque esta palabra clave
se volverá indefinida. Cuando ocurre el evento key down, consola
registramos este objeto de evento
generado automáticamente. Decidí llamarlo
por una variable nombre E, pero puedes llamarlo como
quieras. Si abro este
objeto de evento aquí abajo, puedo ver que contiene la propiedad
key que nos dice qué
tecla se presionó. Eso es exactamente lo que necesito. Si la clave de punto E es triple, igual al operador de
comparación a D, establezca esto en
valor de depuración en su opuesto. Si actualmente es falso,
póngalo en true. Si actualmente es cierto,
póngalo en falso. Esta es una
línea de código muy útil que
nos permite alternar entre
verdadero y falso fácilmente. Solo quiero que este código se
ejecute si el modo de depuración es verdadero, solo
quería
ver este campo de flujo degradarse cuando el
modo de depuración está activo. Ahora, si haces clic en Canvas y presionas la letra D en tu
teclado una y otra vez, estás habilitando y
desactivando el modo de depuración. Volveremos a usar este modo de depuración en la clase avanzada donde te muestro cómo trazar formas e imágenes de
letras. Ahora que las celdas individuales en el campo de flujo son
relativamente grandes, podemos ver claramente que
las líneas se rompen y cambian de dirección en los
límites de cada celda. Porque cada celda contiene
un valor de ángulo diferente, influyendo en el movimiento
de estas líneas. Siéntete libre de jugar con el código, dale diferente valor al tamaño de
celda en línea 70. Y luego puedes
ajustar para ese cambio ajustando este Zoom en línea 75, puedes llegar a algunas combinaciones
interesantes. Como aquí donde tengo un patrón bastante interesante
que se ve claramente afectado por el hecho de que las celdas
individuales en el campo de flujo son
50 veces 50 píxeles. Poco a poco
aumentaré la curva, la espiral interna de nuestro campo de flujo de
seno coseno. Belleza de las matemáticas. ¿Sabías que podrías
hacer arte con las matemáticas así?
30. Colores aleatorios: Abro otra ventana del navegador y voy a Google Color Picker. Estoy buscando algo
como esto donde pueda hacer click quiera y me va a
dar ese valor de color. Puedes entrar en cualquier gama
de colores que quieras. Tomo este color
copiando su valor hexadecimal. Lo asigno como esta
propiedad de color de punto en la clase de partículas. Dentro del método de dibujo
en clase de partículas, dije estilo de trazo
a este color de punto. Si todo el campo de flujo era un
solo color como este, no
hay un estilo de
trazo de Colin de punto una y otra vez. Yo lo declararía en alguna parte, así que solo se ejecuta una vez en la primera página de carga para
mejorar el rendimiento. Pero aquí estoy tratando de darle a nuestras partículas una gama de
colores aleatorios. Yo creo una matriz, a esto
lo llamo colores de punto. Pongo este valor
dentro así. Vuelvo a mi recogedor de color. Empecé de un color oscuro, así que voy un poco más claro
en esta dirección, por ejemplo y de nuevo, copio
este valor hexadecimal. También puse ese color similar
pero más claro en la matriz. Este color de punto
será un color elegido aleatoriamente de esta matriz de colores de
puntos. Puedo acceder a ellos
a través de sus índices. Este índice de color de punto
cero es este. Este índice de color de nodo
uno es este. Tomemos otro color
y lo agreguemos a la matriz. Elijo un color más, entro aún más claro. Yo elijo uno más. Esta vez, va a
ser muy ligero. Puedes elegir tantos
colores como quieras. No importa
cuántos colores agregues a esta matriz. Quiero que a cada partícula
se le asigne aleatoriamente un índice de esta
matriz. ¿Cómo hago eso? Por supuesto, mediante el uso de
Math.random entre cero y la longitud de
esta matriz de colores de punto. Sin embargo, Math.random, nos
da unos valores de
punto flotante. No hay índice
1.5 en esta matriz, así que necesito enteros. Envuelvo todo esto
en Math.floor. Y así es como puedes asignar
aleatoriamente un valor de una matriz de valores disponibles a cada objeto creado por una clase. Se puede ver que cada línea
tiene asignado un valor aleatorio, y nuestro efecto se ve
más interesante. Siéntase libre de volver
al seleccionador de color y elegir
su propia gama de colores. Probablemente sería interesante
crear deslizadores para
este zoom de puntos para que los usuarios
puedan controlarlo fácilmente. Puedes hacerlo como un reto
al final si quieres.
31. Diseño adaptable: Si cambio el tamaño de la ventana del navegador, como con cada proyecto de
Canvas, el elemento canvas no
cambiará el tamaño automáticamente. De la misma manera estamos
aplicando EventListener para el evento keydown aquí en el constructor de clases de
efectos secundarios. También puedo crear resize
windows event listener. Estamos dentro de una clase, así que no quiero estar tirando ancho y alto
desde el exterior. Así que vamos a registrar en la consola este objeto de evento
generado automáticamente. Elimino este registro de consola. Y también me quito esta. Así que somos objeto de evento de inicio de
sesión de consola que se generó automáticamente cuando cambiamos el tamaño de la ventana del navegador y activamos resize
event listener. En el interior puedo ver el
objetivo del evento, en este caso el objeto de
ventana del navegador. Y dentro de eso, podemos ver lo nuevo actualizado
en tu altura y ancho. Entonces solo
usaremos estos valores. Consola log e punto
objetivo punto ancho interior, y E punto objetivo
punto altura interior. Ahora puedo cambiar
el tamaño de la ventana del navegador y
puedo ver el nuevo
ancho y alto. Perfecto. Entonces, cuando cambiamos el tamaño, quería establecer ancho y alto del efecto a estos valores. El problema es que también
necesitamos
cambiar el tamaño del elemento canvas en sí. Y nuevamente tendría que llegar fuera de mi clase para agarrarlo. Quería mantener mis
clases modulares. Necesito una referencia al elemento
canvas dentro de mi clase, refactorial este efecto de código solo
esperaré Canvas como
argumento dentro, lo
convertimos a
una propiedad de clase. Y de este lienzo de puntos, ahora podemos tomar ancho
y alto así. Tengo 69 años, ahora nos da acceso
al propio elemento canvas. Cierro la consola. Necesito tomar esta
variable canvas de la línea uno, y necesito pasarla para
afectar al constructor de clase en
el punto en que creamos una instancia de
affect class usando la nueva palabra clave
aquí en la línea 135. En el interior, se convierte a
esta propiedad dot Canvas. Y de su anchura y
altura se extrae. Entonces ahora cuando se dispara el evento de redimensionamiento, llamaré a este
método de redimensionamiento de puntos, que vamos a escribir. Siguiente. Le paso el nuevo
ancho y alto del redimensionar la ventana
del navegador. Obtenemos estos valores de este objeto de
evento autogenerado. Voy a escribir este
método aquí abajo. Dentro de la clase de efectos. Sabemos que espera el nuevo ancho
y alto redimensionados como argumentos. Tenemos una referencia
al elemento lienzo real aquí en la línea 69. Entonces lo tomo, y también tomo
ancho y alto. Copio estas tres líneas
y las pego aquí abajo. Cuando cambiamos el tamaño de la ventana del navegador, obtenemos un nuevo ancho y alto. Establecimos el ancho del
elemento de lienzo al nuevo ancho. Dijimos altura del
elemento de lona a la nueva altura. Luego establecemos las propiedades width y
height
del efecto a estos
nuevos valores actualizados. Si cambio el tamaño de la
ventana del navegador, se ve interesante, pero no estoy seguro si
no estamos desperdiciando memoria así. Si vuelvo a un tamaño más pequeño, las líneas
eventualmente deberían volver al área disponible más pequeña. Y luego cuando
obtengan más espacio, el patrón debería expandirse
al espacio más grande. De nuevo, creo que la forma que prefiero hacer esto es llamar
al método init. Nuevamente, después de cambiar el tamaño de la
ventana. No hagas lo que estoy haciendo ahora. No ejecutes este código porque
si llamo a this.in desde el método de resize y
redimensiono la ventana del navegador. Algo muy malo pasa. Estamos empujando cada vez
más partículas en esta matriz de partículas de puntos, y el efecto se
ralentiza considerablemente. Si subo al método init, puedes ver que cada
vez que se ejecuta el método init, eliminamos la matriz de
campo de flujo y rellenamos con
nueva cuadrícula de ángulos. Necesito hacer lo
mismo con las partículas. Ponemos estas partículas
de punto en una matriz vacía, eliminamos un viejo
objeto de partícula dentro, y creamos un nuevo
conjunto de partículas. En cuanto al rendimiento, esta
no es la mejor solución. No necesitamos partículas nuevas. Podría haber creado un método de reinicio en cada partícula. Y podría haber restablecido aquí las posiciones de las
partículas en
lugar de eliminarlas todas y crear otras nuevas
para reemplazarlas. También podríamos usar la técnica de
pooling de objetos aquí si necesitamos
aumentar y disminuir el número de
partículas dependiendo del tamaño del
lienzo que
estoy haciendo ahora funciona porque estoy llamando a
este método punto init desde dentro resize en la línea 126. Cuando cambiamos el tamaño,
eliminamos el campo de flujo antiguo, degradamos y
lo reemplazamos con un nuevo conjunto de ángulos ahora ajustados al
nuevo ancho y alto del lienzo. Y también eliminamos
todas las partículas. Y creamos un nuevo conjunto con posiciones
aleatorias repartidas sobre la nueva área de lienzo disponible. Por supuesto, para que esto funcione, necesitamos asegurarnos de que
llamamos a this.in it desde el método de resize aquí, supongo que la mayoría de los usuarios no
serán redimensionados y la
página una y otra vez. Entonces la solución está
perfectamente bien.
32. Experimentación con patrones de campo de flujo: La forma del campo de
flujo es lo que
llamo Seno y Coseno de patrón de curva
espiral, un
poco de trabalenguas para personas con un fondo de
lenguaje suave. No estoy seguro si esta forma
tiene nombre oficial. Si lo hace, hágamelo saber, por favor. Es el patrón
que obtienes cuando
usas aumento de posiciones en una cuadrícula bidimensional como valores de
ángulo pasados
a seno y coseno. Vemos la fórmula aquí. Esta línea de código
que determina la forma del patrón. Podemos jugar con él de
muchas maneras diferentes y obtener resultados
muy diferentes. Mira lo que pasa si sustituyo la multiplicación por la
suma aquí. ¿O qué pasa si hago eso aquí? ¿O intento esto? Yo ajusto el zoom. Interesante.
También puedo ajustar la curva. Puedes simplemente cambiar aleatoriamente
los operadores aquí y tal vez te encuentres con algo interesante
que no he probado. Nuevamente, así es como puedo
alejar lentamente el patrón. Puedo aumentar la curva. Y debido a los cambios al operador que hicimos al calcular una cuadrícula angular ahora cambia la dirección
de todo el patrón. Esto se ve bien.
Tal vez podría usar este efecto para el fondo espacial en la próxima clase de
desarrollo de juegos. Incluso podría hacer que esto
reaccionara a algunos objetos. Aprenderemos más sobre
eso en la siguiente parte, donde te muestro cómo hacer que
las líneas fluyan alrededor del texto. Sorprendentemente, hacer menos iguales aquí también
cambiará el patrón. Se hará más
evidente cuando me aleje. Creo que esto se
debe a que cambiamos en cuyo punto las celdas de la
cuadrícula se rompen a una nueva fila. Si vuelvo a
la multiplicación aquí estamos de vuelta al patrón espiral
habitual. Ahora sólo estoy jugando con él. Intento cambiar en Zoom. Cambio de curva. También puedo hacer ambas firmas aquí. O puedo intercambiar seno y coseno. Creo que está claro
cómo funciona esto. Ahora, siéntete libre de jugar con él y hacer tus propios experimentos.
33. Dibujo de texto: Aquí abajo en el cristal de efecto
principal, tenemos el método init. Se divide en una
cuadrícula y crea valores de
ángulo usando esta fórmula
trigonométrica. Todavía quería
dividirme primero en grilla. Entonces en lugar de este algoritmo, quiero dibujar
texto en Canvas y calcular los valores de ángulo de
la
cuadrícula de campo vectorial a partir de ahí. Dibujemos ese texto primero. Para mayor claridad, pondré ese
código en un método separado. Yo lo llamaré dibujar texto. Voy a necesitar acceso al objeto de contexto
CTX desde aquí para que pueda sentar las propiedades de
Canvas desde aquí. Al principio, simplemente sacaré variable
CTX directamente
de la línea dos. Refaccionaremos
esto en un minuto. A partir de ahí, accedo a la propiedad de
fuente y la configuro a
500 píxeles de impacto. Quiero letras grandes en negrita. Entonces llamo al método
filtText incorporado, que espera al menos
tres argumentos, el texto a dibujar y coordenadas
x e y
donde dibujarlo. El texto que quiero
dibujar es el JS, porque hoy estamos aprendiendo
sobre JavaScript. Coordenada horizontal
será este ancho de punto, el ancho de Lona veces 0.5. El centro del lienzo
horizontalmente, coordenada
vertical y será
esta altura de punto veces 0.5, la mitad del lienzo verticalmente. Como pueden ver, estoy
tirando de la variable CTX de línea a directamente
dentro de mi clase. Quiero seguir buenas prácticas y mantener nuestras clases
autónomas. Entonces voy a refaccionarlo. Voy a necesitar acceso a CTX desde el
método Draw text así como desde el método init porque ahí es donde se
llamará al método de texto dibujado. También necesito acceder a ese mismo contexto desde
dibujar un método de cuadrícula. Dado que necesitamos CTX en tantos lugares diferentes en
toda la clase de efectos, elegiré esta
siguiente solución. Tenemos ctx aquí en la línea dos. Me aseguraré de afectar al constructor de
clase esperado como argumento. Y dentro lo convertiré una propiedad de clase llamada
este contexto de punto. Así. Usaremos este contexto de punto aquí y aquí dentro del método
draw text. Dentro de la tasa de drogas también, ya no se esperará como argumento
proveniente del exterior. En cambio, en todos estos lugares, usaré esta propiedad de clase de
contexto de punto que acabamos de crear. También usamos contexto
dentro del render. Ya no esperará
el contexto como argumento. También voy a eliminar contextos
argumento pasado para dibujar método en partículas y
aquí pasado para dibujar una cuadrícula. Creo que aquí cometí
algunos errores. Tened un segundo conmigo, por favor. De hecho tengo que
pasar este contexto de ley para dibujar método sobre
partículas como esta. Bien, ejecuto el código, me sale un error. Abro el constructor de
clase de efecto de
consola del navegador expect CTX y lo convierte en esta propiedad de contextos de
punto. Necesito asegurarme de
pasarlo CTX aquí abajo en la línea ciento 51 cuando creo
una instancia de esa clase, además, ya no necesito
pasar CTX para renderizar método. Aquí. Tomo el método
draw text y lo llamo desde dentro
del render así. Cuando pasamos las
coordenadas x e y al método filtText, estas coordenadas
establecen el punto
de anclaje de ese texto donde se
dibuja el texto en relación con ese punto de anclaje
depende del valor de los textos, la línea y las propiedades del
lienzo de línea base del texto. La alineación de texto maneja la alineación
horizontal. Ponemos el punto de anclaje del texto a la
mitad del cannabis. Así que mira lo que sucede cuando
pongo la línea de texto al centro. También puedo usar la propiedad de
línea base de texto para alinear el texto verticalmente en relación con esas coordenadas de
punto de anclaje. Lo puse en medio. Una vez más. Cuando
dibujas texto sobre cannabis, los valores que pasas a coordenadas
filtText x e y definieron el punto de anclaje donde se asienta el
texto en relación con ese punto de anclaje depende qué valores le des a las propiedades de texto, línea y línea
base de texto. Por defecto, el texto
se alinea a la izquierda horizontalmente y la
línea base alfabética verticalmente. Los colocamos a centro, medio para obtener
texto centrado así. Esto es muy importante de
entender si alguna vez
necesitas trabajar con
texto en lienzo HTML,
estableceré el debug en
true para habilitar el modo de depuración, quiero que este texto sea
visible cuando esté en modo de depuración. Oh, tengo un error. La consola me está diciendo que está aquí. Necesito usar este contexto de punto aquí también para dibujar mi cuadrícula. Probablemente ya lo
noté antes. Entonces cuando estamos en modo de depuración, quiero ver degradar el campo
vectorial. Y quiero que veas estas grandes letras blancas que
determinarán la forma
del campo de flujo. Al poder mostrar
y ocultar este texto fácilmente presionando la
letra D en el teclado, al ingresar
al modo de
depuración hará que el efecto sea más fácil de
entender y modificar. Render interior. Digo si
esto es el debug es verdadero, solo entonces dibuja una
cuadrícula y dibuja texto. Ahora, puede presionar la
letra D una y
otra vez para activar y desactivar el
modo de depuración.
34. Qué son los datos de píxeles: Dentro del método init, quiero dibujar
a x en este punto. Recuerda que el método init
se ejecutará una sola vez en la primera carga de la página
y creará un campo vectorial y un sistema de
partículas para nosotros. Después de dibujar estas grandes letras
blancas sobre Lienzo, quiero que escaneen
Canvas en busca de datos de píxeles. Mi objetivo final es saber qué celdas de la cuadrícula
son formas de letras vencidas y qué celdas de cuadrícula contienen solo el fondo vacío negro. Lo hago escaneando cannabis en busca datos de
píxeles después de
dibujar ese texto en él. Y analizaré esos datos de
píxeles y los
mapearé en la cuadrícula. Voy a llamar incorporado
get imageData método. Este método devuelve un objeto de datos de imagen
generado automáticamente que representa los datos de píxeles
subyacentes para una
porción específica de cannabis. Se esperan cuatro
argumentos para especificar qué porción de cannabis
queremos analizar. Quiero pixel de datos de todo
el elemento canvas. Entonces, desde la coordenada cero-cero hasta este ancho de punto,
esta altura de punto. En otras palabras, obtener ImageData. Escanearé una porción específica de cannabis en busca de datos de píxeles, podemos extraer colores y coordenadas de
cada píxel de ella. Hacer eso, necesito
entender cómo se organizan los datos en este objeto de
datos de imagen autogenerado? Asignaré esto a una variable
constante que llamo por ejemplo píxeles, y nuestra consola la registrará. Puedo ver el
objeto de datos de imagen aquí en la consola. Lo abro y puedo ver que tiene ancho y alto
del área escaneada. Esto es importante. Necesitamos conocer estos
valores para que podamos extraer las coordenadas x e y
de cada píxel de este. Si conocemos el ancho, cuántos píxeles tenemos, muy fila de datos, sabemos después de cuántos píxeles esta matriz rompe
a otra línea. Se escanea el lienzo. Y en el mismo orden creamos nuestra cuadrícula angular fila por
fila de arriba a abajo, yendo de izquierda a derecha en cada fila. Si abro esta matriz de datos, aquí es donde se almacena toda la
información de píxeles. En realidad es muy sencillo. Simplemente tiene una larga
secuencia de enteros. consola de mi navegador divide esta
matriz extremadamente larga en bloques, pero en realidad es una
larga línea de números. ¿Cómo se
traduce eso en píxeles? Puedo ver que este es
un tipo especial de matriz llamada UI y T8 clamped array. Solo puede contener enteros de ocho bits
sin signo
sujetos para organizar 0-255. Sabemos por la
declaración de color RGBA en CSS que cada color puede ser representado por una combinación de rojo,
verde y azul. Cada color tiene un valor 0-255. Y diferentes combinaciones
de estas nos permiten crear cualquier color en CSS RGBA declaración
de color. El valor de opacidad Alfa es 0-1. Aquí en esta matriz de píxeles, alfa también se representa
por un valor 0-255. Debemos recordar que la matriz de datos de
píxeles es una
línea extremadamente larga de números donde cada cuatro valores representan rojo, verde, azul y Alfa sobre
un píxel, un solo píxel. Entonces este es el píxel uno. Los siguientes cuatro valores, nuestro píxel dos, y así sucesivamente. Puedo ver que el ancho
del área escaneada es 528 píxeles y la
altura es de 464 píxeles. 528 veces 464 es 244,992 pixeles
totales escaneados. Y sabemos que
cada uno de estos píxeles está representado por cuatro
valores en píxeles. Matriz. Valor para rojo, verde, azul y Alfa. 244,992 veces cuatro es 979,968. Aquí podemos ver que
la matriz de datos de píxeles tiene exactamente 979.968 elementos. Así que eso echa un vistazo. Si miro en algún lugar en
el medio de la matriz, debería poder encontrar estos píxeles blancos que
componen las formas de las letras. Aquí puedo ver que
tenemos de 55 a 55 a 55, que es blanco, y 2554
alfa totalmente visible. Sabemos que estos
cuatro píxeles con índice 533,600 en matriz de datos de píxeles representan píxeles
en algún lugar de esta área blanca. Si también cambio el
estilo de relleno, ¿verdad? Abrí la matriz. En su mayoría veo
píxeles negros son ceros, ceros 00 opacidad porque el fondo de nuestro
lienzo es transparente. Aquí puedo ver esos
píxeles rojos a 55 leer cero, verde, cero azul a 55 Alfa. Estos valores representan un píxel rojo
completamente visible, en
algún lugar del área roja, sabemos que estos píxeles son
el texto dibujado en Lienzo.
35. Manejo de datos de píxeles: Bien, entonces el método init ejecutará todos los que están en la
primera carga de página y en su interior estamos
tratando de crear una cuadrícula de ángulos,
un campo vectorial. Dibujamos texto y nos
escaneamos con ese texto dibujado en él con el método get ImageData
incorporado. Ahora, estamos manteniendo todos los valores de píxel dentro de
esta variable de píxeles. Voy a comentar este código que calcula los ángulos espirales para cada celda de la cuadrícula usando nuestra fórmula especial de seno
y coseno. En cambio,
haré la forma del texto de las letras para determinar los ángulos retenidos en cada
celda del campo vectorial. Para ello, necesitamos
usar bucles anidados for. Nuevamente, el bucle for exterior
recorrerá Canvas fila por fila, saltando por tamaño de celda. Cada vez que ingresamos a una nueva fila, establecemos el tamaño
de celda en 20 píxeles. Aquí en la línea 75, puedo mostrar
y ocultar esta cuadrícula
hecha de 20 veces 20 celdas presionando la letra
D en mi teclado. el interior, el bucle
for interno
recorrerá cada fila horizontalmente
de izquierda a derecha. También saltando de celda a
celda por valor de tamaño de celda. Ojalá ahora entendamos
cómo estos dos anidados para ciclo ciclo sobre el lienzo fila
por fila de arriba a abajo. Cada vez que ingresamos a una
nueva celda en la cuadrícula, necesitamos calcular un índice. Ya calculamos el
índice aquí arriba en la línea 40. Esta fórmula nos ayuda
a convertir las
coordenadas x e y en un solo valor que representa el índice en una matriz. A medida que recorremos la cuadrícula
celda por celda, fila por fila, quiero hacer coincidir
esa posición de celda con un índice correspondiente
a estas coordenadas en matriz de píxeles para
que sepa qué datos de
píxeles se escanearon
para esta celda en particular. Una coincidencia en las
coordenadas x e y de la celda. Actualmente estoy
recorriendo con estos bucles
anidados for a un índice específico
en matriz de píxeles para extraer datos de píxeles
para esta área de lienzo. Nuevamente, esta es esa
fórmula donde
multiplicamos el número de fila
por el ancho. Entonces obtenemos píxeles por fila más x, lo que representa
sin embargo muchos píxeles estamos actualmente en nueva fila. Esta vez, estamos
tratando de hacer coincidir el índice en matriz de datos de píxeles. Sabemos que cada partícula está representada por cuatro
elementos, cuatro enteros, 0-255, representados en rojo, verde, azul y Alfa. Entonces, para obtener ese índice correcto, multiplica esto por cuatro. Ahora conozco el índice en
matriz de píxeles que corresponde a las coordenadas x e y de esta celda en particular en el campo
vectorial, el grado. Quiero el color con el que
empiezo, ¿no? El rojo será
matriz de píxeles en ese índice. Verde será el único
índice que viene después. Entonces índice de píxeles más uno. El azul es índice más dos. Entonces tenemos Alfa,
índice más tres. Entonces obtenemos el valor rojo
del siguiente píxel, verde, azul, alfa,
y así sucesivamente y así sucesivamente. Entonces tenemos rojo, verde y azul de cada píxel. La combinación de estos
valores
nos dará el color del píxel
subyacente. Ahora mismo, todos los píxeles de
texto son rojos, pero eso lo cambiaremos pronto.
36. Conversión de colores en ángulos: Mi objetivo ahora es
hacer que el color de las letras afecte la
dirección del flujo, el ángulo en
la cuadrícula del campo vectorial, por ejemplo,
los píxeles
rojos empujan el
flujo hacia la derecha. color azul fluye hacia abajo, color
verde fluye
hacia la izquierda, por ejemplo, y todos los valores de color
intermedios nos dan un
ángulo en algún lugar entre
estas direcciones. Hay muchas maneras en las que puedo
convertir colores en ángulos, y podemos lograr muchos efectos
diferentes aquí. La forma más fácil
sería
convertir de alguna manera los tres
valores de rojo, verde y azul en un
solo número. Puedo, por ejemplo generar un valor en
escala de grises a partir de
este RGB, los colores se
calibran manera que cuando los
tres colores para rojo, verde y azul son iguales, el color resultante
es un tono de gris. El color está en algún lugar del espectro de la escala de grises
sin un sesgo hacia la vista roja, verde o azul. Podemos convertir a escala de grises obteniendo el
promedio de los tres, rojo más verde más
azul dividido por tres. Ahora, podría crear un efecto de escala de grises
a partir de esto tomando ese valor promedio
y aplicándolo nuevo al rojo, verde y azul. Pero en realidad solo
quería tomar ese único valor promedio y
quiero convertirlo
a un valor de ángulo. Tenemos una gama de
colores en escala de grises que va 0-255. Y quiero mapear estos
valores dos ángulos, 0-6, 0.28 rad, 6.28 rad convertir a
360 grados, un círculo completo. Por lo que los colores pueden fluir
en cualquier dirección dependiendo del valor de la
escala de grises de esa área, ya que sólo estamos operando
en valores positivos. Entonces la fórmula es muy sencilla. Toma la relación entre
la escala de grises actual de esta celda en el
campo vectorial y el valor máximo. Y aplicar esa relación
a ese valor de ángulo. Digamos que si la escala de grises es 127.5, eso es a mitad de 50
por ciento entre el valor mínimo de cero y
el valor máximo de 250. 527 punto 5/255 es 0.5. Tenemos la relación, y ahora la multiplico por el
rango angular máximo de 6.28 rad, lo que nos dará la mitad
de ese valor, 3.14. 3.14 es pi semicírculo. Por cierto, si la escala de
grises es por ejemplo 63.75, 63.75 dividido por el valor máximo 255 nos
da una relación de 0.25, 25 por ciento hacia el valor
máximo, un cuarto. Aplicamos la misma relación al valor de ángulo
máximo 0.25 veces 6.28 nos da 1.57 rad
medio círculo por cuarto. Básicamente estoy tomando la relación, relación entre
el valor actual en escala de grises
y el valor máximo de
color posible de 255. Y estoy aplicando esa relación
al rango de ángulo 0-6, 0.28 rad. Debido a que usamos la
escala de grises así, el flujo resultante estará
influenciado por cuán claros u oscuros son los colores en
el espectro de escala de grises. Te voy a mostrar a lo que me refiero cuando pongamos en marcha la animación. Quiero limitar la cantidad de
decimales que obtenemos aquí ya que no hay necesidad de
calcular valores de ángulo minúsculos. Dos decimales están bien. Puse toda la
expresión entre paréntesis, así puedo llamar
a JavaScript incorporado al método fijo en él. Se lo paso a, quiero
sólo dos decimales. Bien, entonces a medida que se ejecuta el método
init, establecemos el campo
de flujo en una matriz vacía. Aquí abajo, llenaré
la matriz con una cuadrícula de valores de ángulo método de empuje de
matriz incorporado. Y vamos a empujar un objeto con la propiedad
x establecida en la coordenada x, coordenada
horizontal desde
el bucle for interno a medida que saltamos por tamaño de celda dentro de
cada fila celda compra-venta, y será el índice y desde el bucle for
exterior a medida que saltamos por valor de tamaño de celda sobre cannabis fila por fila
de arriba a abajo. El valor del ángulo de color es esta gama de colores en escala de grises convertida en un
valor de ángulo en radianes, lo que asegurará
que las partículas fluyan en una dirección diferente
sobre diferentes colores. En consola, podemos ver
ese objeto de datos de imagen. De hecho, no quiero que apunte a todo el objeto, sino solo a la matriz de píxeles, que se mantiene aquí dentro de
la propiedad data. píxeles serán
objeto ImageData devuelto por obtener ImageData
método incorporado datos de punto. Estamos apuntando directamente
a esta matriz ahora. Ahora lo vemos en
la consola aquí. matriz de campos de flujo ahora
contiene objetos con propiedades de ángulo x, y y de color para cada celda de la cuadrícula de campo
vectorial. Tenemos que asegurarnos de tener en cuenta este cambio cuando
la actualización las posiciones de las
partículas aparecen dentro del método de
actualización en la clase de partículas. Aquí estamos tirando del
valor del ángulo de la matriz de campo de flujo dependiente de la
corriente de partículas X e Y
posición en Canvas. Ahora, hay un objeto con tres propiedades en cada índice, así que necesito acceder a su propiedad angulada de
color aquí. Así, bonito,
algo está pasando. Tenemos dos problemas que resolver. Solo quiero ejecutar este bloque de
código que coincida con la posición de la
partícula con un objeto que representa una celda
en el campo de flujo. Si hay un objeto en
ese índice en el Dan
tiró del ángulo de color, eso solucionará el problema
donde las partículas se mueven fuera de los límites de
Canvas entre recites. El segundo número, si
estás codificando a lo largo, puedes alejar el zoom y
puedes ver que ya estamos dibujando en un campo de flujo
con forma de letras JS, pero por alguna razón está
sesgado a la derecha. ¿Por qué es eso? Voy a hacer la fuente
más pequeña para que podamos ver que tenemos la forma, pero ¿por qué está
distorsionada así? Estoy haciendo la celda más pequeña. Ahora podemos ver claramente el campo de flujo
tiene forma de letras JS, pero está sesgado de una
manera extraña. De hecho,
me tomó unos minutos darme cuenta de lo que está pasando, pero avancemos rápidamente
a la solución. Si sabes por qué está haciendo eso antes de
que lo revele, pausa el video y
escríbalo en los comentarios. Ahora mismo, ves
aquí arriba estamos configurando ancho y alto del
lienzo
al ancho y alto actuales
de la ventana del navegador. El problema es que cuando
creamos el campo de flujo, si el valor del tamaño de celda en
la clase de efecto principal, el ancho y alto de cada
celda en la cuadrícula no es un número por el que el
ancho del lienzo se pueda dividir. Sin ningún resto,
obtendremos algunos
píxeles sobrantes cuando
rompamos línea a medida que escaneamos Canvas fila por fila
de arriba a abajo. A medida que bajamos fila por fila, esos
píxeles sobrantes al final de cada fila se acumulan hasta que
el campo de flujo se degrada. Y el campo de flujo se degrada. El número de elementos
allí no
coincide exactamente con el número de celdas
que podemos caber en Canvas. Entonces las filas se empujan cada
vez más hacia la derecha. Hay múltiples
formas de resolver esto. Solo tenemos
que asegurarnos de que el ancho del lienzo sea divisible por tamaño de celda
sin ningún resto, sin ningún valor sobrante. Lo solucionaré estableciendo el ancho del
lienzo a un tamaño específico. Pero también puedes usar una fórmula dinámica aquí usando
el operador resto. Si querías
mantenerlo a pantalla completa, si quieres mantener la funcionalidad
responsive. Dije ancho de lienzo
a 600 píxeles. Y debido a que el tamaño de celda en la
línea 75 se establece en 20 píxeles, 600 es divisible por 20
sin ningún resto, lo que estamos obteniendo
la forma correcta. También estableceré la
altura del lienzo en 600 píxeles, o tal vez 500 veces 500. Cuando cambio el tamaño de Canvas, nuestro método de cambio de tamaño del cliente se activa y vuelve a romper
la forma
porque permite que el ancho del lienzo
sea algo que no es directamente divisible por el
tamaño de celda sin un resto, directamente divisible por el
tamaño de celda sin un resto,
puedo
asegurarme de que solo investigue poco el tamaño si el nuevo ancho
es divisible por tamaño de celda. O simplemente puedo
comentarlo por ahora, aquí
abajo en línea y 92. Y debido a que Canvas es
500 veces 500 píxeles, quiero que esté centrado exactamente en la
mitad de la página. Eso lo puedo hacer con CSS. Ya se ha posicionado
absoluto, así que le doy un top 50 por ciento, izquierda 50 por ciento, y transformar traducir
-50% -50 por ciento. Por supuesto, puedes
posicionarlo de una manera diferente
dependiendo de dónde lo desees. Ahora solo
pondré el fondo en el elemento body en negro. Creo que esto se ve
bien por ahora. Aumento el tamaño de la fuente. 450 tal vez. Sí, estamos convirtiendo el
color a un ángulo. Entonces mira por dónde
fluyen las partículas cuando el texto es correcto. Y mira lo que pasa con
su dirección de movimiento. Cuando cambio el
color a verde. El ángulo azul en realidad es
similar a leerlo porque no estamos extendiendo
la gama de colores en sí, sino
que lo estamos convirtiendo primero a escala de grises, y luego estamos
convirtiendo eso en ángulo. Parece que el azul y el rojo tienen un valor de escala de grises muy similar. Verás la mayor
diferencia en ángulos al usar colores que
sean claros u oscuros. Colores que están muy separados en el espectro de escala de grises. Marrón. Probemos algo
mucho más ligero, amarillo. Podemos ver claramente que
la dirección
del flujo está influenciada
por el color, por el color del texto, perfecto.
37. Flujo y degradación: Podría dejarlo aquí, pero
estaba jugando con él y se me ocurrieron más cosas realmente geniales que
quiero compartir contigo. Esta es siempre mi parte favorita donde tenemos toda
la lógica en su lugar. El efecto está corriendo
y puedo experimentar. Sabemos que los
diferentes colores empujan el flujo de partículas en
diferentes direcciones. Entonces veamos qué
sucede cuando el relleno
del texto no es
solo de un color, sino un degradado que transita
de color a color. Me pregunto cómo
será eso. Una variable personalizada llamada
el gradiente uno, y yo llamo a Canvas incorporado
create linear gradient method. Espera cuatro argumentos, x e y del punto inicial, y x e y del punto final. El degradado se dibujará a lo largo de
una línea entre estos dos puntos. Quiero un degradado desde
las coordenadas de esquina superior izquierda, cero-cero hacia las
coordenadas de la esquina
inferior derecha efecto ancho
y altura de efecto, que son lo mismo que ancho
y alto del lienzo. Ahora puedo tomar ese
gradiente una variable y
llamo incorporado agregar el método de
parada de color de ella. En el desplazamiento 0.2, el color
será blanco, por ejemplo 0.8 offset. Intento azul completo. Ahora solo puedo establecer FillStyle a esta variable de gradiente uno. Impresionante, esto es tan genial, como se curva el flujo a medida
que pasamos del azul al blanco. Ahora que entendemos esto, podemos experimentar con diferentes rangos de color
y diferentes gradientes. Agrego otra parada de color en el punto cero para el color amarillo. 0.6 será, por ejemplo, verde. Sólo puedo jugar con los valores de color
para ver qué flujo obtengo. Es interesante cómo cambia la dirección del
flujo a medida que los colores transitan
siguiendo el degradado. Olvidé mencionar una característica
importante de filtText y trazo de texto
incorporado en los métodos Canvas, podemos pasarles quinto argumento
opcional para definir el
ancho máximo del texto. Diré que el ancho máximo
del texto es el
peso del lienzo. Ahora bien, si el texto es más largo, se aplastará
para encajar en el área. Si quiero algunos de márgenes, puedo decir este
ancho de punto veces 0.8. Y el texto tomará el máximo del 80
por ciento de Canvas. Tomará un 80 por
ciento si le damos más espacio ajustando el
ancho del lienzo a un valor mayor. Vuelvo a Tamaño de lienzo
500 veces 500 pixeles. Cambié la palabra para fluir. Podemos cambiar la fuente
a Helvetica, por ejemplo, volver al impacto. Y los textos serán JS. Quiero que fluya para
curvar más a la derecha. Entonces juego con los valores de
color para conseguir que el gradiente influya en la
dirección del campo de flujo. Esto se ve bien. Copo este bloque de código y también renombro
todos estos gradientes. Y lo uso como
FillStyle online 112th. Vuelvo a jugar con los valores para ver qué pasa. Sé más o menos
en qué dirección fluye cada color, pero en su mayoría es de prueba y error. Esto se ve interesante. Creo un degradado tres
copiando este bloque de código y usando eso como FillStyle
en línea ciento 18. Esta vez será
un gradiente radial, por lo que necesitamos
pasarle seis argumentos, x e y del
punto central del círculo interno. Es radio. Así que quería que
el círculo interno comenzara exactamente en medio del lienzo horizontal
y verticalmente. Y el radio será de diez pixeles. El borde exterior
del círculo de gradiente radial volverá a estar desde la mitad de Canvas y el radio será
un ancho de escritorio. Interesante. Ajusto los
colores para ver qué forma obtengo. Se puede ver como el gradiente
radial afecta el flujo de
una manera diferente. Este me gusta mucho. Voy a mantener los tres
gradientes que
definí para poder intercambiar entre ellos
más tarde si quiero.
38. Consejos, trucos y experimentos: Cuando los ángulos cambian de dirección, es un giro brusco. Podría funcionar para usted, pero tal vez queremos que las
líneas giren más gradualmente cuando cambie el ángulo en
el campo vectorial. Estamos manteniendo el valor del ángulo
actual para cada partícula aquí en
la clase de partícula principal. Estamos cambiando este valor
dentro del método de actualización para que coincida con el valor de ángulo de
la cuadrícula en el campo de flujo. Voy a crear otra propiedad
aquí llamada new angle. Y voy a comprobar la
diferencia entre el ángulo actual
y el nuevo ángulo. Y en lugar de cambiar a
ese nuevo ángulo instantáneamente, cuando las partículas ingresen a una nueva
celda en la cuadrícula del campo de flujo, simplemente
empujaremos
las partículas hacia ese nuevo ángulo en cierta
fracción de su diferencia. O para reducir los
cálculos necesarios, en lugar de calcular
la fracción de la diferencia entre el
ángulo existente y el nuevo ángulo, solo
puedo tener un valor establecido
llamado carácter de ángulo. Será un pequeño
valor en radianes. Aquí abajo en el método de actualización, dije nuevo ángulo dos, un ángulo almacenado en la
celda del campo vectorial. Y digo si el ángulo
actual de la partícula es
más que nuevo ángulo, reducir el
valor de ángulo de la partícula por el
valor de carácter de ángulo que definimos, mover el ángulo existente un
paso más cerca del nuevo ángulo, elijo hacerlo de esta
manera para ahorrar rendimiento. También se puede decir
cambiar el valor del ángulo una décima parte de la diferencia
entre ángulo y nuevo ángulo, lo que le dará curvas
más graduales a expensas del rendimiento porque
se requieren más cálculos. De lo contrario, si el ángulo es
menor que el ángulo u, aumente el valor del ángulo
por carácter de ángulo. Uno más en otro lugar
establecemos ángulo a nuevo ángulo. Ahora puedes ver que los
giros bruscos se han ido y solo estamos empujando
suavemente las partículas hacia ciertos valores de ángulo. Ajusto el valor del
carácter del ángulo para empujarlos un poco más fuerte. O podemos hacer un
valor aleatorio aquí entre algún rango pequeño para que cada partícula se
curva de manera diferente. Puedo ajustar maxlength. Puedo cambiar el modificador de velocidad. Tenemos toda la lógica en su lugar. Si quieres, puedes
jugar con él para ver qué variaciones de este
efecto te pueden llegar a ocurrir. Entonces esta es mi manera eficiente de
rendimiento muy básico, cómo hacer que las partículas
cambien de dirección más gradualmente a medida que el flujo sobre la rejilla de celdas
en el campo de flujo. También me gustaría poder
controlar cuántas
partículas fluyen dentro las formas de letras
y cuántas fluyen en el área fuera
de las letras. Ahora, es completamente aleatorio, pero no tiene por qué serlo
cuando las partículas se reinician. Quería comprobar
si se está restableciendo dentro de las formas de las letras
o fuera de ella, en
algún lugar del
área transparente alrededor de la letra. Si está fuera de las letras, quería volver a intentarlo. Voy a tener una variable
llamada intento. Comenzará en cero. Al principio. Voy a tener una
bandera llamada reset success. Inicialmente será falso. Cuando las partículas se
reinicien dentro de las formas de las letras, cambiaremos esto a true. Voy a tener un bucle while. Cuando las partículas se restablecen, quería probar cinco veces. Hará cinco intentos de elegir
aleatoriamente una posición en
algún lugar de Canvas para intentar restablecer dentro de las formas de las letras. Siempre y cuando los intentos
sean menores cinco y mientras el éxito de
reinicio sea falso, crearé un índice de prueba. Será una celda aleatoria en
algún lugar de la matriz
de campo de flujo. Compruebo si este índice de prueba
tiene alfa más que cero, lo que significaría que es la celda en el campo de flujo la que tiene algún color visible
en sus datos de píxeles, lo
que significaría que es
una de las letras. Alternativamente,
será transparente, lo que significaría que es el
fondo vacío alrededor de las letras. Si tiene Alfa más de cero, significa que encontramos una
de las celdas de letras. Entonces establecemos
las posiciones x e y de la partícula a las posiciones x e y de la celda en el
campo de flujo. La grilla. Aquí abajo puedo ver que las celdas
llenas de fluido, los objetos dentro de la matriz de
campos de flujo contienen valores de ángulo x, y y de color. Entonces esta X e Y
vendrán de ahí. Dije que esas coordenadas x
e y son
el primer punto en el camino al agregarlo a
la matriz de historia. Y reinicié el temporizador de nuevo
a términos maxlength dos. También estableceré reset
success a true. Es importante destacar que necesito
asegurarme de que cada vez que
intentemos hacer esto, aumentemos el intento por uno
para que cuando lleguemos a cinco, este bucle while, y
no queremos crear
un bucle while interminable. Continuará sólo
mientras ambas
condiciones sean ciertas. Entonces solo cuando los intentos son menores a cinco y
al mismo tiempo, siempre y cuando el
éxito del reset sea falso. Si ejecuto el código,
no se restablece en absoluto. Entonces eso indica que esta
condición en la línea 78 siempre está devolviendo falso. Es porque no estamos empujando este valor Alpha en nuestros objetos de celda de campo de
flujo. Cambié los intentos aquí
arriba a 50. Entonces aquí abajo estoy calculando
alfa en línea 160. Necesito asegurarme de
que el valor realmente termine dentro de la matriz de campo de
flujo. Así. Las líneas perfectas se
restablecen dentro de las letras. Dije max, intento volver a cuatro después de que el
bucle while haya terminado. Si después de intentar
restablecer cuatro veces, todavía no hemos
encontrado una celda con alfa más de cero y reset, el éxito sigue siendo falso. Reiniciaremos las coordenadas x
e y de esa partícula en algún lugar
aleatoriamente alrededor del lienzo. Todavía no está restableciendo
partículas fuera de las formas de letras. Incluso cuando baje
a sólo dos intentos. ¿Qué tal un solo intento? Voy a resolver esto. Sólo dame un segundo, ¿verdad? Tengo que poner estas nuevas
posiciones dentro de la matriz de historia. Y lo más importante, tengo que
restablecer el temporizador de nuevo a maxlength veces dos para que
las partículas se animen. Bonito. Entonces ahora cuando las partículas se restablecen, este código intentará
una cierta cantidad de veces restablecer las partículas
dentro de las formas de las letras. Y si no encuentra que la celda en cierta
cantidad de intentos, simplemente
restablecerá la partícula algún lugar aleatoriamente
alrededor de Canvas. Podemos ajustar
cuántas partículas
queremos restablecer dentro y fuera de las formas de letras
cambiando el número de
intentos en la línea 75. El último intento, las partículas
menos probables son encontrar las
formas de las letras en el tiempo. Así que podrían resetear afuera. Puedo aumentar el
número de partículas y aumentar el tamaño de las celdas. Podemos ver que la mayoría de las partículas ahora se
restablecen dentro de las formas de letras, pero ocasionalmente obtenemos un
reinicio en otro
lugar, en algún lugar afuera, puedes ajustar el número
de partículas y tamaño de
celda a lo que
quieras y a lo que sea que tu
computadora pueda manejar aquí. Puedo eliminar este código. Creo que ahora todos entendemos cómo estos valores
afectan a la animación. Tal vez 2000 partículas. ¿Qué pasa si agrego color blanco a la matriz de colores para
algunos reflejos? Interesante, lo vuelvo a quitar. Intento el gradiente uno para cambiar la dirección
del campo de flujo. Degradado también. Creo que mi favorito
es el gradiente tres. ¿Cuál prefieres?
Yo aumento maxlength, lo que sí tiene efecto
en el rendimiento. Las líneas más largas toman más potencia
informática para dibujar. Entonces creamos una cuadrícula, dibujamos texto en Lienzo. Analizamos ese tipo de nosotros
con textos dibujados en él. Para los datos de píxeles, recorrimos
esos datos de píxeles en una cuadrícula para extraer los valores de color y
las coordenadas de cada píxel. Y convertimos estos resultados
en colores en ángulos. A partir de esa información,
creamos un campo de flujo, una cuadrícula de ángulos, donde la dirección de los ángulos es influenciada por el texto
que se dibujó en Canvas. Puedo eliminar este bloque de código. Entonces creamos un sistema
de partículas aquí. A lo mejor quería que las partículas comenzaran
a fluir desde las formas de las letras incluso
en la primera carga de página. Entonces activaré manualmente el método de
reinicio en cada
partícula a medida que las cree, lo que los obligará a hacer algunos intentos de encontrar celdas en el campo de flujo que
contenga algunos valores de color, celdas que están sobre
las formas de letras. Cambié el texto para que fluyera. puede ver que se mete con el gradiente radial,
que se espera. Aumenta el ancho del lienzo
a 1500s píxeles. Puedo crear max-width
del texto aquí abajo. Puedo usar gradientes para, para cambiar la dirección del flujo. Esto se ve interesante. ¿Qué tal el gradiente uno? Probablemente te diste cuenta de
que esto
funcionaría en imágenes
así como solo estoy usando get ImageData para obtener formas de letras que
fueron dibujadas en Canvas. ¿Quieres aprender
a usar esto en las imágenes? Te voy a mostrar exactamente
cómo hacer eso en la siguiente parte. Espero que
te estés divirtiendo.
39. Los campos de flujo de imágenes explicados: Entonces construimos un campo de flujo de texto y experimentamos con él. Vuelvo a poner el texto a js mayúscula para
que encaje en la pantalla
y podamos verlo todo. Puedes descargar
imágenes que estaré usando en la
sección de recursos a continuación, o puedes usar las tuyas propias. Estaré usando imágenes
pequeñas, 200,
200 píxeles con un
tamaño alrededor de 10 kb. El tamaño de las imágenes
es importante para el rendimiento. Entonces, si estás usando
tus propias imágenes, piensa en eso y optimiza las imágenes antes de
usarlas para este proyecto, si quieres que tu animación
funcione sin problemas, este efecto se ve muy bien
con algunas imágenes específicas. Desde mi experiencia,
el mejor resultado es con formas simples que
tienen colores degradados, ya que esto hará que la
curva de flujo a su alrededor sea muy agradable. En index.HTML, creo
un elemento IMG con un ID de estrella y la fuente
apuntará hacia esa imagen. Si recuerdas de
la parte anterior, el truco fue dibujar
texto en Canvas y luego
analizar esos datos de píxeles
y crear un campo vectorial, una cuadrícula de ángulos
a partir de esa forma. Yo quiero hacer
lo mismo aquí con una imagen. Ahora, quería dibujar esta
imagen en Canvas y luego quiero escanearnos eso un poco
con esta imagen dibujada en ella. El problema es que
hay algunas limitaciones a este Cross-Origin
Resource Sharing es una medida de seguridad que
no nos permite dibujar ninguna imagen aleatoria en Canvas y luego escanear ese
Canvas en busca de datos de píxeles. Si la imagen no es
del mismo origen, ese tipo de nosotros se considera contaminado por datos de origen cruzado. Y tu código terminará
con un error de consola para dibujar imagen en Canvas y la
escanearla con get ImageData, esa imagen necesita ser
considerada del mismo origen. Si está ejecutando
su código desde un servidor y la fuente de la imagen aquí apunta a una imagen almacenada en la misma dirección
del servidor. Entonces va a funcionar. Quiero que esta base de código sea flexible y que funcione
fácilmente a nivel local. No quiero repasar la configuración de un
servidor local en este momento. Entonces, una posible solución alternativa
es convertir la imagen en
sí misma en una llamada cadena de datos
base 64. Para ello, podemos usar URL de
datos construida en el método
JavaScript, o hay muchos sitios web que lo
harán por nosotros en segundos. En resumen, para evitar problemas de uso compartido de
recursos de origen cruzado, estoy convirtiendo el archivo de imagen en
sí mismo en una cadena de datos, y luego usaré esa cadena de
datos como fuente de imagen. Yo hago eso por Google y
P y G, dos base-64. Tenga en cuenta que la imagen
no tiene que ser PNG. También trabajará con
otros formatos. Voy a elegir por ejemplo este sitio web en línea PNG tools.com. Pero los otros sitios
funcionarán de manera similar. Arrastre y suelte la
imagen que quiero
convertir desde mi computadora
a este campo. Y convertirá instantáneamente todo
el archivo de imagen en
una línea de código muy larga. Utilizar una imagen pequeña como sea posible en términos de
ancho y alto, así
como kilobytes. De lo contrario, este código
será demasiado largo y
causará problemas de rendimiento cuando lo
animemos en un minuto. Idealmente, utilizar las
imágenes y proporcionar. Y luego una vez que tengas
un efecto de trabajo, puedes cambiar a un archivo de imagen
diferente. Esta cadena de datos base 64 necesita comenzar como esta imagen de dos puntos de
datos. Si no es para ti, haz clic en esta casilla de verificación
para
convertirla a un formato específico
que necesitemos. Copio esta línea de código extremadamente
larga y la pego como atributo
fuente aquí. En Visual Studio Code, puedo hacer clic en Ver y
ajuste de palabras para que el
archivo de código sea más manejable. Como puede ver, estamos
dibujando esa imagen de estrella, pero nunca usamos el archivo de imagen
real. Esta larga cadena
de código
reemplaza completamente el archivo de imagen en sí. Y como todo ese código está
dentro de nuestro archivo HTML índice, se considera el mismo
origen en todas las circunstancias. Y por lo tanto podemos hacer operaciones
avanzadas de píxeles en él con lienzo
HTML sin desencadenar un error de Canvas
contaminado. Déjame mostrarte. Es fácil conseguir que
esto funcione ahora, realmente no
quiero dibujar
el elemento image en sí, así que tomo su id y lo
escondo con CSS. En cambio, quiero dibujarlo en Canvas donde el JavaScript, voy al
efecto principal de clase y
creo una nueva propiedad
llamada esta imagen de punto. Señalé esta variable a ese elemento de imagen
usando su ID como de costumbre. Entonces tenemos una variable apuntando a la imagen estelar
aquí en la línea 110. Dibujémoslo en Lienzo. Aquí arriba dije lienzo
ancho a 500 pixeles. Igual que tengo este método de
dibujar texto. Para mantener nuestro código organizado, crearé un
método separado para dibujar la imagen. No quiero llamarlo
una imagen de dibujo porque ese nombre ya existe para
un método Canvas incorporado,
llamaré a este método personalizado por ejemplo dibujar una
imagen de campo de flujo para mayor claridad. En el interior, tomo estos contextos de punto y llamo método de imagen de
dibujo incorporado. Necesita al menos
tres argumentos, la imagen a dibujar y las coordenadas
x e y
donde dibujarla. Para probarlo, llamaré draw
flow field image from inside render porque no soy un definido en ancho y
alto en línea 148, la imagen se está dibujando
en su tamaño original. Podemos redimensionarlo o estirarlo pasando en valores
para ancho y alto, 300 con 100 de altura. ¿Qué tal ancho
completo y altura total del lienzo? Bonito. Y si quisiera que la imagen se centrara exactamente en el
medio del cannabis, independientemente del
tamaño que elija. Eso también es muy fácil. Creo una variable auxiliar
llamada tamaño de imagen. Digamos que quiero que el ancho
y el alto de la imagen sean 70% del ancho del lienzo. Lo uso aquí como
ancho y alto. Sí. Ahora dije coordenada x a
la mitad del cannabis. Entonces este ancho de punto veces 0.5 y hago menos la mitad
del tamaño de la imagen. La imagen está centrada
horizontalmente. Para coordenada y vertical, hago altura de Lona veces 0.5. El medio de una especie
de como verticalmente menos Tamaño de la imagen veces 0.5. Perfecto. Esta es una
fórmula muy simple para centrar la
imagen en medio
del lienzo HTML. Cuenta el hecho de que imágenes en Lienzo
se dibujan igual los rectángulos de la
esquina superior izquierda yendo a la derecha y hacia abajo, dependiendo de su
anchura y altura. Si lo redimensiono ahora a cualquier tamaño, siempre se dibujará
en medio de Canvas. Voy a hacer el 80 por ciento
del ancho del lienzo, por ejemplo como ya expliqué antes, aquí creamos un campo de
flujo degradado, dibujamos algo en Canvas. Luego analizamos ese
tipo de nosotros con ese texto o esa forma
o imagen dibujada en él para datos de píxeles para crear
una cuadrícula de campo vectorial a partir de él convirtiendo
colores en ángulos. Ya tenemos toda esta lógica de la parte anterior en su lugar. Entonces todo lo que tengo que hacer
aquí es reemplazar esta parte donde dibujamos texto con código que dibuja la imagen. Yo llamo dibujar
imagen de campo de flujo aquí y aquí vamos. Eso fue fácil. Realmente
no quiero dibujar la
imagen real de la estrella sobre ella así. En cambio, lo tomo de
aquí y quiero dibujarlo detrás de las partículas solo
cuando el modo de depuración esté activo. Entonces, desde dentro de este bloque de código, ahora podemos activar y desactivar el
modo de depuración presionando letra D en el teclado para mostrar y ocultar
el campo vectorial, la cuadrícula y la imagen de origen. Puedo cambiar el tamaño de la imagen. Podemos ver que siempre se mantiene centrado y
que todo funciona bien. Si cambio el tamaño de Canvas
, cambiará el tamaño de la
imagen con él. Porque dije que el tamaño de la imagen estelar para ser del 80
por ciento del ancho del lienzo.
40. Trucos de manipulación de colores: No podría dejar esto y
dejarte hacer tus propios experimentos. Pero de nuevo, estaba jugando mucho con el código y
me preguntaba, cómo puedo conservar y usar los colores originales
de la imagen fuente. ¿Correcto? Ahora, estamos usando colores de esta
matriz de colores de puntos en la línea 25, los colores de la
imagen fuente en sí no son visibles. Aparte de utilizarlos para determinar ángulos
del campo de flujo. Ya estamos escaneando esa imagen en
busca de datos de píxeles, así que ¿por qué no intentar usarla? Escribí múltiples
soluciones diferentes para este fin. Decidí
mostrarte esta por
las razones que voy a explicar
como implementamos, si tienes algunas ideas de cómo
mejorar esta base de código,
por favor házmelo saber. En cada objeto de partícula, almacenaré una propiedad separada para rojo, verde y azul. Esto no es necesario
si me acaban de tomar los colores como son
de la imagen original. Pero cuando veas cómo se ve
eso, probablemente
estarás de acuerdo en
que necesitamos una forma de
hacer una transición dinámica y
gradual entre colores a medida que
las partículas y líneas viajan de celda a
celda sobre el campo de flujo. Por eso voy a
necesitar los tres colores por separado así. Déjame mostrarte por qué. Voy a concatenar
declaración de color RGB aquí. Siéntase libre de usar una plantilla
literales aquí en su lugar, si esa es su sintaxis preferida, simplemente
haré RGB
plus, más coma, más verde
más coma, más bu
más corchete de cierre. Ahora, podemos cambiar el
color de las partículas ahí dentro estableciendo estos
dos valores diferentes. Bien, eso funciona bien. Voy aquí dentro del método
init donde dibujamos ese archivo de imagen original en Canvas y
lo escaneamos para obtener datos de píxeles. Voy a necesitar tres valores
para rojo, verde y azul. Así que los pongo a disposición
empujándolos como propiedades
adicionales
dentro de la matriz de campo de flujo. Así que ahora es una especie
de escaneado para datos de
píxeles celda por
celda, fila por fila. Cada vez que ingresemos a una nueva celda
en la degradación del campo de flujo, almacenaremos todos estos
datos para cada celda en la cuadrícula dentro de nuestra matriz de campo de
flujo. Ahora sé cuál es el valor rojo, verde y azul de cada celda
individual en la cuadrícula. Así puedo hacer coincidir el color de las partículas con
estos valores a medida que las partículas
fluyen sobre Canvas. Dentro del método de actualización
en la clase de partículas. En esta área, extraigo el elemento en este índice
particular dentro matriz de campos de
flujo en una
variable solo porque
quería que la sintaxis en este bloque de código
fuera más fácil de leer. Y también para el rendimiento, saqué ese índice de
la matriz solo una vez, y luego uso esa referencia existente
en múltiples lugares. Ahora puedo
reemplazarlo aquí y aquí. Este es el mismo código. Simplemente lo refactorizamos. Entonces, en esta área, extraemos el valor del ángulo de matriz
satisfecha para
manejar el movimiento de las partículas. En esta área, extraeré los valores de
color de esa
celda en el campo de flujo. Yo solo quería las
celdas que contienen datos de
píxeles de la imagen si tienen alfa
más de cero, porque conozco las celdas
transparentes con cero alfa o el fondo
alrededor de la imagen. No nos importan los de aquí. Entonces, si esta celda
no es transparente, tome esta propiedad de lectura de puntos
en este objeto de partícula. Definimos en la línea 25 y la configuramos para leer la propiedad
que
acabamos de extraer de propiedad de lectura del campo de
flujo contenida en esta celda en particular en el campo de flujo sobre
el que la partícula se está moviendo
actualmente. Haremos lo
mismo por este
verde oscuro y este azul oscuro. Ahora, quiero usar estos valores de color actualizados para construir
una cadena de colores RGB nuevamente. Entonces copio la línea 28 y la uso
aquí abajo en la línea 62. Bonito. Estamos viendo los
colores reales de la imagen. Hacer esto como una gran cantidad de cálculos
adicionales por fotograma de
animación a nuestro efecto. Pero depende de ti decidir
si vale la pena o si
prefieres usar
colores predefinidos como lo hicimos antes, solo te
estoy mostrando
lo que es posible. Como es habitual, todo esto se puede optimizar de muchas maneras
diferentes. Las técnicas avanzadas de optimización están fuera del alcance de esta clase, pero podemos hablar de ello
más adelante en algún otro curso. Se puede ver que las
líneas están parpadeando. ¿Sabes por qué es eso? Es porque cuando
la partícula viaja de celda azul a celda
blanca, por ejemplo, el color de toda la
línea larga que la partícula está arrastrando detrás de ella
cambiará a ese nuevo
color instantáneamente. Cambiará instantáneamente el color de toda
la línea porque cada
línea es solo una llamada de dibujo. Así que podemos simplemente
cambiar el color de una parte de esa línea con
el código que escribimos hasta ahora. Nuevamente, múltiples soluciones aquí. Podría ajustar nuestro código para
verificar si el color cambió. Y luego usa ese color actualizado solo para algunos segmentos de línea. O lo que voy a hacer aquí, voy a cambiar el color
de toda la línea. Pero en lugar de que ese
cambio de color ocurra instantáneamente, voy a calcular gradualmente
la diferencia entre los dos colores sobre
múltiples pasos de animación. Por lo que los colores no
solo se intercambiarán instantáneamente, van a hacer una transición lenta. ¿Cómo lo hacemos con código? Ya que estamos en la sección
avanzada, utilizaré
una sintaxis simplificada más avanzada. Esto se llama operador
ternario, el único operador JavaScript
con tres operandos. Lo usaremos aquí como una simple declaración de una línea
if else. Definir una condición, una expresión a evaluar.
Si es verdad. Signo de interrogación, haz esto. De lo contrario, si es falso,
colon, haga esto. Entonces, a medida que las partículas fluyen sobre la cuadrícula del campo de flujo y extraen valores
de color de esas celdas. Compruebo si el valor rojo de la
partícula es el mismo que el valor rojo de la celda en el campo de flujo en este índice. Si lo es, simplemente no hagas
nada y déjalo en paz. Si el valor rojo no
es el mismo, en lugar de
reasignarlo instantáneamente al nuevo valor rojo actualizado, simplemente
aumentaré o disminuiré gradualmente valor
rojo en una fracción
de su diferencia. Digamos por una décima parte
de la diferencia. Podríamos haber hecho lo mismo
con los valores de ángulo aquí, pero decidí que es más eficiente en el
rendimiento usar un valor establecido almacenado
dentro del carácter de ángulo, aunque usar diferencias de
ángulo graduales
crearía curvas más naturales
en el movimiento de las partículas. Puedes probarlo
más tarde si quieres. En fin, verifico si el rojo
es lo mismo que el rojo nuevo. Si es así, déjalo en paz. Si no lo es, acercarlos
un paso más, pero no del todo a la vez
para conseguir una transición gradual. No puedo ver si esto
está funcionando o no. Entonces hagamos lo mismo
por el verde. Así. Tengo que tener
cuidado con la sintaxis aquí. Creo que está funcionando. Hagámoslo también por el azul. Así. Solo estoy revisando mi código
para ver si todo está bien después de todo eso
copiando y pegando. Sí, esto es bueno. Estoy usando 0.1 aquí. Este valor
determinará qué tan agudo o gradual será el cambio de
color, qué tan rápido
pasarán los colores
del color existente
al nuevo color objetivo. Antes de que la transición de
color ocurriera instantáneamente para toda la línea de partículas
multisegmentadas. Ahora sucedieron poco a poco
y el efecto se ve bien. Creo que esto es muy especial. No puedo creer que
pasáramos de dibujar una sola línea animada a doblar
formas de campo de flujo alrededor de las imágenes. Si seguiste
todo el camino hasta aquí, este es un gran logro, bien hecho, y
felicidades por tu dedicación al aprendizaje. Seguro que eres un
codificador creativo. Aquí en la línea 86, puedo controlar cuántas partículas se reinician
dentro de la forma y
cuántas se reinician fuera de ella cambiando cuántos intentos
le damos a cada partícula para tratar encontrar esa forma entre reinicios. Para asegurarnos de que esto funcione, podemos usar una imagen diferente. De nuevo, ten en cuenta imágenes demasiado
pequeñas si es posible. Las formas simples como las estrellas
funcionan muy bien para este efecto. Puedes descargar
la otra imagen que te
proporcioné en la sección de
recursos, o puedes usar tu propia imagen. Ahora, copio esta línea
de código
extremadamente larga y voy a indexar HTML. Necesitamos líneas para estar rompiendo
para reemplazar la fuente. Entonces, si todo está en
una línea para ti, puedes ir a Ver envoltura de
palabras para hacer líneas de freno
VS Code Editor así. Para reemplazar la cadena de datos. En Visual Studio Code, sólo
puedo seleccionar el inicio
de esta cadena muy larga. Me desplazo hasta el final. Presiono la tecla Mayús
en mi teclado. Y mientras mantengo
presionada la tecla Mayús, hago clic donde quiero que termine
la selección. Destacará todos los textos intermedios y
puedo presionar Eliminar. Bonito. Ahora que sé que
eliminé la imagen antigua, pego la nueva
cadena de datos base 64 de la nueva
imagen. Yo lo guardo. Y aquí vamos, estamos dibujando una imagen diferente y podemos ver los colores se están
extrayendo correctamente de los datos de píxeles de
origen. Puedes consultar
el código fuente en la sección de recursos a continuación. También jugaré con
el código ahora e
incluiré algunos de mis
otros experimentos de bonificación para que los descargues e
inspecciones si quieres inspiración sobre dónde
llevar este efecto más lejos. Me gustan los proyectos de codificación creativa porque estamos aprendiendo sobre animación así como el programa
general y principios. Hicimos muchas funciones de
manipulación de matrices y para bucles hoy en día, por ejemplo, todas
estas son muy importantes
en todas las ramas de la codificación, no solo para la animación. Muchas gracias por
pasar el tiempo conmigo. Espero que hoy tengas
mucho valor. Te veré más tarde.