18 marzo 2007

Si vas a tardar, por lo menos avisa...

No hay cosa más desesperante para un internauta que querer ver una página que tarda mil horas en bajar. Y peor tantito si ni siquiera sabe si es que no se ha interrumpido la descarga, cuanto tiempo va a terminar, etc.

Es por esto que Flash tiene la infraestructura necesaria para poder informarle al usuario que se está cargando la página con un montón de instrucciones ActionScript que le pueden brindar toda la información necesaria para que no se desespere (o por lo menos se aguante hasta que acabe). Así que ahora voy a discutir la manera en hacer esto.

Para explicar como se hace este procedimiento, llamado "preloader" por algunos doctos en el lenguaje del país de las hamburguesas y la Coca-Cola (o simples malinchistas que quieren apantallar), hice cuatro proyectos de Flash:
  1. El primero solo muestra un texto que dice "Cargando" con puntos suspensivos que van aumentando. Descárgalo aquí.
  2. El segundo quita esa animación chafa y hace un símbolo clip de película (o movie clip) que se encarga de parar la ejecución de la película y mostrar el porcentaje cargado y los bytes cargados vs. los totales. Descárgalo aquí.
  3. El tercero solo agrega a ese símbolo una barrita que va avanzando según el porcentaje descargado. Descárgalo aquí.
  4. El cuarto solo agrega el cálculo del tiempo que falta para descargar todo. Descárgalo aquí.

Lo que tienen en común todos es que sirven de preludio para una animación que carga varias instancias de un símbolo que tiene un cuate que camina (o corre, no entendí como está esa movida) y de fondo tiene parte de una canción (parte del soundtrack de la película Matrix). El caminador fue muy sencillo hacerlo: bajé de internet el "sprite" de un monito, separé los cuadros usando Photoshop, los importé a la biblioteca de mi proyecto Flash e hice un símbolo clip de película (movie clip) que tiene una animación donde cada cuadro tiene una de las imágenes cortados.

Voy a ignorar todo el rollo de la animación de los proyectos como tal para poder concentrarme en el preloader (ya me gustó la palabrita, pero conste que no es por malinchista, jeje). Mi animación consta de muchas capas (layers), pero las que nos interesan son dos: Acciones y Preloader. Acciones tiene 6 frames y Preloader tiene 5. Así se ve una parte de mi pantalla de la línea de tiempo:


Primero voy a mostrar lo que tienen los 4 fotoramas clave (keyframes) de la capa Preloader. Aquí están en su debido orden, bien ordenados como se ordena al ordenar (o sea, primero va el contenido del fotorama 1, luego el 2, etc.):


¡Listo! Fácil, ¿no? En el primer fotorama (frame) pongo el texto "Cargando" y en cada uno de los siguientes le iba aumentando un punto suspensivo. Ahora, como pudiste observar, mi capa (layer) Acciones tiene código en el primer fotorama. El código usa una variante del if llamado ifFrameLoaded que sirve para ver si ya se ha cargado un fotorama especificado (en nuestro caso, con el _root._totalframes estoy verificando si ya cargó el último fotorama). En el caso que ya haya terminado de cargar todo, le digo que comience a m,ostrar lo que hay desde el fotorama etiquetado como "inicio" (abajo escribo una notita sobre la ubicación de esta etiqueta). El código del primer fotorama de la capa Acciones se ve así:


El otro pedacito de código que usé en la capa Acciones fue la del fotorama 5 donde le digo que se regrese al primer fotorama a seguirle (o sea, cierro un ciclo que va a seguir tocando hasta que se cumpla la condición ifFrameLoaded . Para esto, basta escribir una sola línea de código:


Lo único que resta decir de la capa Acciones es que el fotorama 6 tiene una etiqueta, "inicio", para que el código explicado con anterioridad sepa a a partir de que fotorama continuar después de haber cargado todo a la memoria.

Con eso ya la armamos grave para el primer proyecto, el más sencillito. Para probar este y todos los proyectos que voy a explicar aquí, presiona CTRL+ENTER y de la ventana que aparece, ve al menú View->Simulate Download para que muestra la animación como si la estuvieran bajando de internet (la velocidad a la cual quieres simular lo puedes editar en View->Download Settings).

Ahora va el proyecto 2. Aquí hago algunos cambios importantes. En primer lugar, elimino la capa Acciones y renombro el Preloader a PreCargador (pa' que vean que se me quita lo malinche, jeje). En esta capa solo pongo una cosa: un símbolo de clip de película llamado preloader (y vuelve la malinche). La línea de tiempo se ve así:


Ignora las capas que están arriba de PreCargador, que son las mismas que el en proyecto 1. Ahora, voy a analizar lo que contiene el símbolo preloader que es quien hace toda la chamba. Al editar el símbolo, se ve así:


Pero, ¿qué es esto? Fíjate primero en la línea del tiempo. Tengo dos capas: Código, que contiene el código ActionScript que va a hacer todo el teje y maneje del buisness y la capa Resto que contiene, buen, el resto. La capa del resto está bien fácil. Solo tiene dos cajas de texto donde voy a desplegar los datos acerca del porcentaje de lo que se ha cargado (txtProgreso) y la cantidad de bytes cargados y totales (txtBytes). Lo único que tienen de "raro" es que en las propiedades especifiqué que son de tipo Dynamic Text (ver imagen abajo). Esto le dice a Flash que ese texto lo voy a modificar usando ActionScript.


Una pequeña nota para optimizar la película. Es posible, para mi texto (sobre todo si es dynamico) definir los caracteres que quiero que se incluyan en mi proyecto. Es decir, en lugar de agregar todo el alfabeto completo de un tipo de letra en el archivito Flash, puede solamente agregar unas cuantas letras. Esto lo puedes hacer presionando el botón Embed de la barra de propiedades del tipo de letra:


Al presionar este botón aparece una ventana como la que sigue.


En la lista superior puede especificar qué símbolos incluir y, en dado caso que necesitas algo de más, puedes escribirlos en la cada de texto inferior (en mi caso agregué un espacio y el signo %). Abajo le da el número de símbolos (glyph) que va a incluir en el proyecto. Así, en lugar de guardar todo el alfabeto completo de un tipo de letra determinado (256 símbolos), solo estoy guardando 12 (10 dígitos numéricos, el espacio y el signo "%"). Con esto se ahorra un poco de espacio en el producto final.

Sigamos, pues, con dar información al usuario acerca de la razón de la tardanza. Todo el código interesante está en la capa Código. Este es el código guardado en el primer fotorama de esta capa:


El stop() común y corriente seguramente lo conoces en demasía, pero lo interesante es que le agrego al principio _root. Al decirle _root.stop(), le estoy diciendo a Flash que haga la acción de parar toda la animación (stop()) en la primera escena. No olvides que estamos dentro de un símbolo que, para funcionar con la línea del tiempo de la escena 1, tiene que hacer referencia a él con el _root. Si quisiera, en lugar de _root, podría ponerle _parent que quiere decir que pare todo lo que está haciendo la escena "padre" (o sea, la escena que contiene a este objeto).

Ahora vámonos al fotorama 2, el cual contiene todo el código chuvidubis. Aquí pongo el código y abajito lo explico:


Las primeras 5 líneas estoy inicializando variables que voy a usar. Uso las funciones de Flash getBytesLoaded y getBytesTotal para saber el número de bytes que he cargado a la memoria y el número total de bytes que tiene el archivo, respectivamente. Los divido entre 1024 para reportar el número de kilobytes (algo que se me hace más interesante que los puros bytes a secas). Con una simple resta calculo el número de kilobytes que faltan bajar. Después de esto, calculo el porcentaje de lo que lleva y el que falta (si no te recuerdas de la manera de sacar porcentajes, puedes ir sacando tu libro de 5to año de primaria y repasarlo tantito). Las dos líneas que siguen le asignan valor a los textos dinámicos explicados anteriormente: txtProgreso y txtBytes.

Al final hace la comparación que regula hasta cuando se va a seguir usando esta animación. Si lleva menos del 99% del archivo bajado (valor que calculé en la variable porCientoCargado), vuelvo a tocar la escena 2 de este símbolo. En caso contrario, toca lo que hay en la escena 1 (_root) a partir del fotorama 2.

¡Listo! De esta manera tienes texto que le indica al usuario cómo va la movida. Al probar tu película (diciéndole que simule la descarga como se dijo antes), se debería ver algo así:


¡Listo! Con eso ya tenemos el texto. Ahora vamos a hacerlo más gráfico. A la capa Resto le voy a agregar un rectángulo abajo del texto (este es solo una prueba: tu lo puedes poner en vez de las letras, arriba, abajo, sobre ellas, etc.). Selecciono el relleno del rectángulo y lo hago un símbolo Clip de película. Ese símbolo, cuya instancia llamé barraCarga (ver imagen abajo), lo incluyo en el símbolo preloader, donde estoy trabajando, y voy a usar la propiedad _xscale que tienen los símbolos para ajustar su tamaño. Sé que existe también la propiedad _width, pero se me facilita más trabajar con la escala que es un porcentaje (y como yo ya calculé el porcentaje, todo sale de maravilla).


Al código del fotorama 2 solo le agrego una línea nueva: barraCarga._xscale = porCientoCargado; Recuerda que porCientoCargado es una variable que calcula el porcentaje de lo que se ha cargado ya en la memoria. Para no dejar las cosas a medias, el código en el fotorama 2 de mi símbolo preloader es así:


¡Listo! Ahora le estoy dando tanto los datos como texto y de manera gráfica con una barrita que se va llenando. Para pasar al último proyecto, voy solamente a agregar otro texto dinámico abajito de la barra llamado txtSeg el cual va a desplegar el número de segundos faltantes para que comience el show. Para esto, voy a usar la función getTimer la cual almacena el número de milisegundos transcurridos desde que arrnacó la animación. El el código que he ido cambiando tantas veces en el paso de estos proyectos, lo voy a editar una vez más para agregar un par de líneas. Comienzo creando otra variable donde voy a calcular el número de bytes por segundo de la transmisión actual. Esto se calcula en base al número de bytes que se han cargado desde que se arrancó la animación (si no recuerdas como, ahi revisa tus libros de matemáticas de la primaria). Esta línea es así:

kBytesSeg = kBytesCargados / (getTimer() / 1000);

Luego calculo el tiempo que falta por cargar todo con esta instrucción:

tiempoRestante = kBytesFaltantes / kBytesSeg;

Y al final, desplego los valores de los tiempos así:

txtSeg.text = Math.floor(tiempoRestante) + " segundos restantes"

Por todos lados estoy usando la función Math.floor para que me devuelva la parte entera de un número. Si no, se ve medio feo que diga que está bajando 89.907665 % del archivo o que faltan 2.34127 segundos para que termine de cargar la animación.

Creo que con estos ejemplos se entiende como hacer un preloader en Flash. Si tienes dudas, deja un comentario o mándame un emilio y trataré de contestarte a la brevedad. ¡Nos vemos!
Publicar un comentario
Related Posts Plugin for WordPress, Blogger...