Construye una galería dinámica de flash con control deslizante

En este tutorial, crearemos una galería que muestra todos los archivos de imagen en un directorio determinado. Un control deslizante se utiliza para navegar fácilmente a través de las imágenes.


Paso 1

Configure un nuevo documento Flash AS3 y un archivo ActionScript en blanco. Vamos a crear la clase principal primero; llámalo "Galería" y guárdalo como "Galería.as". A continuación se muestra el código para configurar la primera clase:

 package public class Gallery public function Gallery (): void 

En Flash, ahora podemos establecer esto como la clase base ingresando el nombre en el cuadro de entrada debajo de la configuración de publicación del documento. Puedes probar una "traza ('hola mundo')" en la función Galería para probar si está funcionando.


Paso 2

Antes de continuar con la clase principal, es mejor comenzar con el control deslizante. El código es bastante fácil de entender y podría arrojar algo de luz sobre cómo se hacen las cosas en AS3.

Cree dos nuevos clips de video: un control deslizante y un controlador para el control deslizante. No es necesario exportar el control deslizante o el buscador para ActionScript, ya que solo necesitamos aplicar algunas funciones al controlador. Establezca la clase para el identificador como "Asa". Ahora podemos crear una nueva clase llamada "Manejar" y, si se guarda en el mismo directorio, Flash utilizará automáticamente esta clase para la manija. Asigne un nombre de instancia como "control deslizante" y "la manija".


Paso 3

El siguiente es el código completo para el identificador que explicaré en pasos. Debe guardarse como "Handle.as" en el mismo directorio que su .fla. De esta manera, Flash ejecutará el código una vez que se use una instancia con un nombre de clase "Handle".

 paquete import flash.display.MovieClip; import flash.events.MouseEvent; import flash.events.Event; la clase pública Handle extiende MovieClip public var goToX: Number = x; deslizador de var privado: MovieClip = MovieClip (parent) .slider; private var mousePos: Number = 0; función pública Handle (): void buttonMode = true; addEventListener (MouseEvent.MOUSE_DOWN, moveHandle); stage.addEventListener (MouseEvent.MOUSE_UP, stopHandle);  función privada moveHandle (_e: MouseEvent): void mousePos = mouseX; stage.addEventListener (MouseEvent.MOUSE_MOVE, followHandle);  función privada stopHandle (_e: MouseEvent): void stage.removeEventListener (MouseEvent.MOUSE_MOVE, followHandle);  función privada followHandle (_e: MouseEvent): void var newPos: Number = stage.mouseX - mousePos; var orgX: Number = x; if (newPos < slider.x ) goToX = slider.x; else if ( newPos > (slider.x + slider.width) - ancho) goToX = (slider.x + slider.width) - ancho; else goToX = newPos; x = goToX; if (goToX! = orgX) dispatchEvent (nuevo evento ("deslizando", verdadero)); 

En las primeras líneas, creamos algunas variables para contener los datos que podemos usar en cada función de esta clase. La variable del control deslizante contiene una referencia a la instancia llamada "control deslizante" en el elemento primario. Lo necesitamos para calcular correctamente la posición x a la que se debe mover la palanca. En el constructor, configuramos "buttonMode" como verdadero, de modo que aparece un cursor de mano cuando se desplaza sobre el control. Además, agregamos dos listers de eventos para escuchar los eventos del mouse.

 la clase pública Handle extiende MovieClip public var goToX: Number = x; deslizador de var privado: MovieClip = MovieClip (parent) .slider; private var mousePos: Number = 0; función pública Handle (): void buttonMode = true; addEventListener (MouseEvent.MOUSE_DOWN, moveHandle); stage.addEventListener (MouseEvent.MOUSE_UP, stopHandle); 

Una vez que ocurre un evento con el mouse hacia abajo, se agrega un oyente adicional. Este oyente permanece activo siempre que el movimiento de arrastre no se detenga y llame a la función "followHandle". Se elimina de nuevo cuando se termina el clic del ratón..

 Función privada moveHandle (_e: MouseEvent): void mousePos = mouseX; stage.addEventListener (MouseEvent.MOUSE_MOVE, followHandle);  función privada stopHandle (_e: MouseEvent): void stage.removeEventListener (MouseEvent.MOUSE_MOVE, followHandle); 

Esta última función realmente mueve el mango alrededor. La variable "newPos" almacena la nueva posición a la que debe moverse el controlador. Sin embargo, si esta posición está más lejos del extremo izquierdo o derecho del control deslizante, la posición debe establecerse en el valor máximo posible. Si se mueve el controlador, enviamos un nuevo evento personalizado llamado "deslizamiento", que luego podemos usar para movernos por las imágenes..

 función privada followHandle (_e: MouseEvent): void var newPos: Number = stage.mouseX - mousePos; var orgX: Number = x; if (newPos < slider.x ) goToX = slider.x; else if ( newPos > (slider.x + slider.width) - ancho) goToX = (slider.x + slider.width) - ancho; else goToX = newPos; x = goToX; if (goToX! = orgX) dispatchEvent (nuevo evento ("deslizando", verdadero)); 

Etapa 4

Si todo ha ido bien hasta ahora, debería tener un buen control deslizante funcional como el que se muestra a continuación. Agregue un campo de texto dinámico debajo que contenga el número de la imagen. Asígnele un nombre de instancia como "countTxt" para que podamos solucionarlo más adelante en ActionScript. Porque todavía no hay nada que mostrar, lo llené con el texto "Cargando", que también se mostrará mientras el script carga la primera imagen..


Paso 5

A continuación vamos a crear el script de back-end php. Flash no puede leer el contenido de un directorio local, por lo que necesitamos pasar la información de PHP a Flash. Usaremos XML ya que es fácil de generar con php y aún más fácil de leer nuevamente en AS3.

El siguiente es el código de backp php, guárdelo como "backend.php". El código recorre el directorio "img" y escribe una línea de XML para cada archivo allí. Antes de imprimir necesitamos filtrar el "." y "..." directorios. Como el directorio solo contiene imágenes, no es necesario realizar más comprobaciones..

  ". $ nombre_archivo".\ n ";?> 

Esto dará como resultado, por ejemplo:

  archivo1.jpg archivo2.jpg file3.jpg 

Paso 6

Antes de cargar esto en Flash, vamos a crear una clase para mantener nuestras imágenes individualmente. De la misma manera que creamos la clase Handle, ahora podemos crear una clase Img. Comience con la creación de un clip de película sobre el tamaño que desea que se muestren sus imágenes. Dale un margen de unos pocos píxeles y guarda un poco de espacio en la parte inferior para el texto de la descripción. Agregue un campo de texto dinámico para la descripción y asígnele un nombre de instancia de "descr". Asegúrese de establecer el punto de registro del movieclip en el centro para que podamos escalarlo fácilmente más tarde. Exportarlo para ActionScript bajo el nombre de clase "Img". Ahora borre la instancia del escenario como lo llamaremos directamente desde la biblioteca.


Paso 7

A continuación, cargaremos la información que el archivo php devuelve en nuestro proyecto Flash utilizando ActionScript. Abre la clase de la Galería de nuevo. El siguiente código agrega dos funcionalidades a nuestro proyecto. En primer lugar, crea "imagesClip", un clip de película vacío en el que almacenaremos las imágenes reales más tarde. Usando "addChild" aquí se agrega el movieclip al escenario. Todo lo que se agregue a imagesClip más adelante también aparecerá en el escenario. Para cargar realmente los datos xml, creamos un "URLLoader". Esta clase puede obtener los resultados y ejecutar una función cuando los resultados están en.

 paquete import flash.display.MovieClip; import flash.events.Event; importar flash.net.URLLoader; importar flash.net.URLRequest; la clase pública Gallery extiende MovieClip private var backend: String = 'http: // localhost /… /backend.php'; private var xmlLoader: URLLoader = new URLLoader; var privado xdata: XML; Imágenes de var público: Array = new Array (); public var imagesClip: MovieClip = new MovieClip; Galería de funciones públicas (): void imagesClip.y = 180; addChild (imagesClip); xmlLoader.load (new URLRequest (backend + "?" + new Date (). valueOf ())); xmlLoader.addEventListener (Event.COMPLETE, loadImages);  función privada loadImages (_e: Event): void xdata = new XML (_e.target.data); var i: Número = 0; para cada (var img: XML en xdata.img) images [i] = new Img (); i ++; imagesClip.addChild (images [i]); 

Aquí usamos la función de carga de la clase URLLoader. Para evitar el almacenamiento en caché de los resultados, podemos agregar una fecha simple al final de la URL. Eventlistener comprueba cuando finaliza el URLLoader y luego ejecuta la función loadImages.

 xmlLoader.load (new URLRequest (backend + "?" + new Date (). valueOf ())); xmlLoader.addEventListener (Event.COMPLETE, loadImages);

Esta siguiente función recorre todos los instancias en el xml. Para cada uno de estos crea una nueva instancia de la clase Img. A continuación, lo agregamos al clip de imágenes (esto es solo para probar, ya que más adelante solo queremos que se muestren las imágenes activas).

 función privada loadImages (_e: Event): void xdata = new XML (_e.target.data); var i: Número = 0; para cada (var img: XML en xdata.img) images [i] = new Img (); i ++; imagesClip.addChild (images [i]); 

Paso 8

Para dar más funcionalidad a nuestras instancias Img, crea una clase Img y guárdala como "Img.as". De forma similar a la carga del XML, podemos cargar la imagen y mostrarla dentro del movieclip Img. La carga no debe ocurrir en el constructor o todas las imágenes intentarán cargar al mismo tiempo; Vamos a crear una función separada para hacer esto.

 clase pública Img amplía MovieClip public var id: Number; privado var src: String; private var imageLoader: Loader = new Loader (); principal var privado: Galería; private var orgWidth: Number = 0; var privado Altura: Número = 0;

En el constructor, establecemos una referencia a la clase principal de la Galería para que luego podamos acceder a elementos en el escenario o variables públicas y funciones de la clase principal. La cadena "carga" contendrá la ruta a la imagen que php devolvió, la guardaremos en una variable para poder acceder a ella más adelante.

 función pública Img (cargar: Cadena, m: Galería): void orgWidth = width; orgHeight = altura; main = m; src = carga; 

La función "loadImage" carga la imagen y cuando termina, ejecuta la función "displayImage".

 public function loadImage (): void imageLoader.load (new URLRequest ("img /" + src)); imageLoader.contentLoaderInfo.addEventListener (Event.COMPLETE, displayImage); 

La función displayImage verifica la matriz de imágenes que creamos y carga la siguiente imagen. Establece el suavizado en verdadero en el cargador (de manera predeterminada, el suavizado se establece en falso en las imágenes cargadas dinámicamente). Una vez que comience a escalar o rotar una imagen, es importante establecer el suavizado para que la imagen mantenga su calidad. Como el punto de registro del movieclip Img está en el centro, debemos calcular las posiciones x e y de dónde colocar la imagen. En mi ejemplo he usado un directorio de imágenes con el mismo ancho y alto. Si el ancho y el alto de la imagen cargada son variables, este es el lugar para cambiar el tamaño sobre la marcha. Justo antes de agregarlo como niño, configuramos el texto de la descripción en "src", que contiene el nombre de la imagen..

 función privada displayImage (_e: Event): void if (main.images [id + 1]! = null &&! main.images [id + 1] .parent) main.images [id + 1] .loadImage (); Mapa de bits (imageLoader.content) .smoothing = true; imageLoader.x = main.spaceBetween / 2 - (orgWidth / 2); imageLoader.y = main.spaceBetween / 2 - (orgHeight / 2); descr.text = src; addChild (imageLoader); 

Paso 9

Después de los cambios que hicimos en la clase Img, necesitamos actualizar la forma en que se llama a las instancias en la función loadImages de la clase Gallery. Ahora necesitamos pasar dos argumentos al llamar a un nuevo Img ().

El primero es el nombre de la ruta de la imagen que se necesita cargar, esto lo obtenemos del xml. El segundo es una referencia a la clase principal de la Galería; podemos usar "esto", que apunta a la clase en la que estamos trabajando actualmente. En lugar de agregar las imágenes con addChild al contenedor imagesClip, crearemos una nueva función "goTo". Esta función determinará qué imágenes colocar en la pantalla. El argumento que debemos pasar es el número de identificación de la imagen, el mismo número que la clave de índice en la matriz de imágenes. Cuando las imágenes se cargan por primera vez, estableceremos el enfoque en la primera imagen, cuyo número de identificación es cero.

 función privada loadImages (_e: Event): void xdata = new XML (_e.target.data); var i: Número = 0; para cada (var img: XML en xdata.img) images [i] = new Img (img, this); imágenes [i] .x = 200 * i; imágenes [i] .id = i; i ++;  goTo (0); 

Paso 10

Para usar la función goTo debemos declarar primero una variable "imagesToShow". Esto establecerá la cantidad de imágenes que queremos cargar a la vez en la pantalla. Para determinar la dirección en la que se desplaza el usuario, simplemente verificamos si la imagen que vamos a tener tiene un número de identificación mayor o menor que el anterior..

 función privada goTo (imgId: Number): void var direction: Number; if (orgImgId! = imgId) if (imgId> orgImgId) dirección = 1; otra dirección = -1;

El siguiente "for loop" reproduce todas las imágenes necesarias en la pantalla. Por ejemplo: si configuramos imagesToShow en 5, pasará de -2 a 2. Esto significa que si pasamos el valor de i a la clase Img, podemos determinar dónde se debe posicionar en la pantalla (-2 está muy a la izquierda , 0 centro y 2 al extremo derecho). Por lo tanto, podemos escalar las imágenes más grandes cuanto más centralmente estén posicionadas..

Se incluye una verificación adicional por lo que no activamos las imágenes que no existen (se detiene en la primera y la última). Para cada una de las imágenes activas ejecutaremos la función "makeActive", que crearemos más adelante..

 para (var i: Number = - Math.floor (imagesToShow / 2); i <= Math.floor(imagesToShow/2); i++ )  if( imgId + i < images.length && imgId + i >= 0) imágenes [imgId + i] .makeActive (i, direction); 

Inmediatamente después de colocar las imágenes que necesitamos en la pantalla, comprobaremos cuáles no deberían estar allí y sacarlas del escenario. Dado que todas las imágenes se agregan al contenedor de imágenes de clips, podemos recorrer fácilmente todos los hijos de ese clip de película. Si su ID no está dentro de los que deberían estar activos, ejecutamos el comando "deActive".

 para (var j: Number = 0; j < imagesClip.numChildren; j++ )  var tile : Img = imagesClip.getChildAt(j) as Img; if ( tile.id < imgId - Math.floor(imagesToShow/2) || tile.id > imgId + Math.floor (imagesToShow / 2)) tile.deActive (direction); 

La siguiente línea actualiza el texto del campo de texto dinámico que creamos anteriormente. Dado que los identificadores de las imágenes comienzan su conteo en 0, agregamos + 1 al imgId, de modo que la primera imagen es en realidad la número 1, etc. Podemos obtener el número total de imágenes al acceder a la longitud de la matriz de imágenes..

 countTxt.text = imgId + 1 + "/" + images.length; 

Finalmente, estableceremos "orgImgId" para que la próxima vez que se ejecute la función, se pueda determinar la dirección que se está desplazando..

 orgImgId = imgId; 

Paso 11

Ahora necesitamos las funciones "makeActive" y "deActive" en la clase Img. Estos agregarán la imagen al escenario o la quitarán. Por ahora solo las añadiremos y las colocaremos correctamente. Más adelante también los intercalaremos en su lugar correcto..

La función makeActive primero verifica si ya se ha agregado a imagesClip. Si no se encuentra ningún elemento principal, se agrega al contenedor imagesClip. El padre es entonces el clip de imágenes. A continuación, establecemos la propiedad visible en true. Al desactivarlo, lo configuramos en falso, por lo que es normal que queramos que nuestra imagen se muestre nuevamente cuando se active..

 función pública makeActive (posición: número, dirección: número): void if (parent == null) main.imagesClip.addChild (this);  visible = verdadero;

Existe la posibilidad de que la imagen en sí no se haya cargado todavía. Para verificar esto, verifico si la cantidad de niños es menor que 3. Este número puede depender de la cantidad de formas u otros movimientos de su Img. Si no está seguro de este método, una opción más segura sería declarar un valor booleano al inicio y establecerlo en verdadero en la función displayImage..

 si (numChildren < 3 ) loadImage();

No hay profundidad en AS3, pero una vez que comencemos a escalar y rotar nuestras imágenes, necesitamos asegurarnos de que la imagen en el centro esté por encima de las demás. Como pasamos la posición como un argumento en la función goTo, ahora podemos usarla para establecer el índice de la imagen en el clip de imágenes. El índice de un niño puede compararse con una profundidad, pero no habrá problemas al cambiarlo, ya que los otros clips de movimiento moverán un índice hacia arriba o hacia abajo. Este paso no es necesario si no planeas superponer las imágenes..

 parent.setChildIndex (this, (parent.numChildren-1) - Math.abs (posición));

Por último, determinamos la posición de la imagen. La variable "extra" se usa aquí para averiguar cuánto está alejada la imagen actual del centro. "DefaultWidth" y "spaceBetween" son variables públicas establecidas en la clase principal de la Galería, por lo que podemos acceder a ellas desde cualquier lugar. Como todas las imágenes en mi directorio tienen el mismo ancho, establezco el ancho de banda predeterminado en 195 y el espacio entre 20 en 20. Para mover la imagen a la nueva posición, configuramos la propiedad x al valor x recién encontrado.

 var extra: Number = Math.round (position * (main.defaultWidth + main.spaceBetween)); var newX: Number = Math.round ((main.stageWidth / 2)) + extra; x = newX; 

Paso 12

La función deActive es bastante sencilla, cambia la visibilidad a falso. La dirección ya está establecida como un argumento, ya que lo necesitaremos más adelante para saber en qué dirección enviar la imagen cuando la saque del escenario..

 función pública deActive (dirección: Número): void visible = false; 

Paso 13

Por ahora, las primeras imágenes deberían aparecer en el escenario. Solo falta una funcionalidad El control deslizante aún no está conectado a la función goTo. Sin embargo, dado que ya enviamos un evento personalizado una vez que se arrastra el manejador, no es muy difícil conectar los dos.

Agregue la siguiente línea a la función de construcción de la Galería. Este eventlistener ejecutará la función de diapositiva cada vez que el manejador llame al evento "deslizante"..

 theHandle.addEventListener ("deslizando", deslizar);

Todo lo que necesitamos que haga la función de deslizamiento es calcular qué imagen debe mostrarse en el centro dependiendo de dónde se encuentre el controlador. En la función "control deslizante" y "theHandle" están los nombres de instancia que establecimos anteriormente en los clips de video en el escenario. Para averiguar a qué imagen ir, primero determinamos el porcentaje de la posición del controlador sobre la longitud del control deslizante. Luego, multiplicar eso por el total de imágenes nos lleva a la identificación de imagen correcta.

 función privada slide (_e: Event): void var percent: Number = (theHandle.goToX - slider.x) / (slider.width - theHandle.width); var imgId: Number = Math.round (percent * (images.length - 1)); goTo (imgId); 

Paso 14

Si ha logrado seguir hasta aquí y ha seguido el seguimiento de qué clases importar y qué variables declarar (o ha seguido los archivos de origen), debería tener un ejemplo funcional..


Paso 15

Para finalizar este tutorial, agregaremos la interpolación a las imágenes utilizando TweenLite, un motor de interpolación ligero y gratuito. Las clases de interpolación estándar proporcionadas por Adobe no tienen un buen rendimiento cuando hay muchas actividades. Al probarlos, solían estrellarse o congelarse mucho, mientras que todavía tengo que descubrir tales problemas con TweenLite. La sintaxis de TweenLite es muy sencilla. Lo demostraré comparándolo con una interpolación Flash normal; interpolando un objeto de su x actual a 100 y cambiando el alfa a 0:

 nueva interpolación (objeto, 'x', Linear.easeOut, object.x, 100, 2, true); nueva interpolación (objeto, 'alpha', Linear.easeOut, object.alpha, 0, 2, true);

Ahora aquí está la sintaxis alternativa de TweenLite:

 TweenLite.to (objeto, 2, x: 100, alpha: 0, suavizado: Linear.easeOut);

Paso 16

Vamos a crear una nueva función en la que podamos colocar todas las acciones de interpolación. Nombra "flyTo" y colócalo en la clase Img.

 función privada flyTo (newX: Number, removeAfter: Boolean, scale: Number = 1): void var tweeningOptions: Object = new Object; tweeningOptions.x = newX; if (removeAfter) tweeningOptions.ease = Linear.easeIn; tweeningOptions.alpha = 0; tweeningOptions.scaleX = tweeningOptions.scaleY = 0.3; tweeningOptions.visible = false;  else tweeningOptions.ease = Back.easeOut; tweeningOptions.alpha = 1; tweeningOptions.scaleX = tweeningOptions.scaleY = scale; tweeningOptions.rotation = (Math.random () * 20) - 10;  TweenLite.to (esto, 0.4, tweeningOptions); 

Hay 3 argumentos necesarios para esta función: el valor de x que calculamos anteriormente, si debe eliminarse después de la interpolación y la escala. El parámetro "removeAfter" se utilizará en la función deActive, por lo que la visibilidad de la imagen se puede establecer en falsa una vez que haya llegado al final del escenario. El parámetro de escala solo se usa para la imagen central; Lo mostraremos un poco más grande que el resto..

Vamos a ver las opciones de interpolación para cuando la imagen se elimina del escenario. Primero elegimos una opción de aceleración, en este caso "Linear.easeIn", que proporciona un movimiento lineal normal. En segundo lugar, atenuamos el valor alfa a cero, por lo que la imagen se desvanece. Luego lo escalamos a solo un pequeño porcentaje de su ancho y altura para que se vuelva más pequeño a medida que llega al final. Por último, cuando se completa la interpolación, establecemos la visibilidad en falso.

 tweeningOptions.ease = Linear.easeIn; tweeningOptions.alpha = 0; tweeningOptions.scaleX = tweeningOptions.scaleY = 0.3; tweeningOptions.visible = false;

Cuando una imagen se activa, las opciones de interpolación son diferentes. Establecemos la aceleración en "Back.easeOut" para que las imágenes parezcan volar un poco demasiado lejos y luego recuperarse; Un efecto muy sutil. A continuación, cambiamos el alfa de nuevo a 1 y escalamos la imagen al valor de escala que pasamos a la función. Por último, establecemos una rotación aleatoria de -10 a 10 grados. Si su texto de descripción no se carga después de esta acción, debe asegurarse de que la fuente esté incrustada.

 tweeningOptions.ease = Back.easeOut; tweeningOptions.alpha = 1; tweeningOptions.scaleX = tweeningOptions.scaleY = scale; tweeningOptions.rotation = Math.round ((Math.random () * 20) - 10);

Paso 17

Ahora necesitamos actualizar las funciones makeActive y deActive para que hagan uso de la nueva función flyTo.

En la función makeActive necesitamos agregar un valor x a la imagen para que pueda interpolarse a partir de ese valor original. El valor predeterminado de Width debe establecerse en la clase de la Galería principal y contiene el ancho del escenario.

 función pública makeActive (posición: número, dirección: número): void deactivating = false; if (parent == null) x = (direction == 1? main.stageWidth + main.defaultWidth * 2: - main.defaultWidth * 2); alfa = 0; main.imagesClip.addChild (este);  visible = verdadero; si (numChildren < 3 ) loadImage(); parent.setChildIndex(this, ( parent.numChildren-1 ) - Math.abs( position ) ); var extra : Number = Math.round( position * ( main.defaultWidth + main.spaceBetween ) ); var newX : Number = ( Math.round( ( main.stageWidth / 2 ) /* - ( main.defaultWidth / 2 )*/ ) + extra ); flyTo( newX, false, ( position == 0 ? 1.2 : 1 ) ); 

En la función deActive, todo lo que necesitamos agregar es un valor moveTo que contiene el valor x al que la imagen debe interpolarse. Si ubicamos esto fuera del ancho del escenario, la imagen desaparecerá justo fuera del escenario..

 función pública deActive (direction: Number): void if (! deactivating) active = false; var moveTo: Number = (direction! = 1? main.stageWidth + main.defaultWidth * 2: parent.x - main.defaultWidth * 2); flyTo (moveTo, true); desactivando = verdadero; 

Paso 18

Después de actualizar todo, ahora tenemos una galería funcional. Para ver cómo desaparecen los videos del escenario, echa un vistazo a la versión completa.


Conclusión

La versión final todavía es baja en funcionalidad. Todas las imágenes cargadas deben tener el mismo tamaño y no tienen una vista previa más grande. Puede agregar una función de cambio de tamaño y una opción para ver una vista previa más grande de la imagen cuando se hace clic. Además, se puede agregar una opción para navegar hacia la izquierda o hacia la derecha con botones o con un evento de teclado.

Una vez que entienda el concepto de usar clases para separar y estructurar su código, ayudará en el desarrollo y facilitará las cosas a largo plazo. Espero que hayas disfrutado siguiéndolo!