Hay veces que tenemos una sub-página de nuestro sitio en la cual debemos mostrar varias imágenes, y la carga de las mismas puede demorarse bastante. Vemos la opción de colocar una barra de progreso que mantenga al usuario informado en tiempo real, pero, si son como yo, se niegan rotundamente a colocar algo desarrollado en Flash. Pues bien, para gente como nosotros, JavaScript pone a disposición la propiedad complete de un objeto imágen.

La propiedad complete de un objeto imágen lo que hace es simplemente devolver true si la imágen en cuestión ha terminado de cargarse o false en caso contrario. Únicamente con esta propiedad, el concepto de pre-carga y un poco de manejo de CSS podemos desarrollar la tan querida barra de progreso.

El código que les voy a dejar a continuación se explica por si solo. He colocado comentarios en casi todas las líneas para mejorar su entendimiento. Pueden ver un ejemplo de implementación haciendo click aquí (por favor tengan en cuenta que dependiendo de su velocidad de conexión y la carga del servidor puede que la barra de progreso se mueva demasiado lento o demasiado rápido). El código se compone de 4 funciones, las cuales son:

  • iniciar(): función llamada en el evento onload. Se encarga de crear todos los objetos img necesarios para comenzar con la carga de las imágenes que corresponda. También esta función asignará algunos valores iniciales a variables posteriormente utilizadas.
  • calcularProgreso(): esta función se encarga de ir monitoreando el atributo complete de todas las imágenes que se van a cargar y estima el porcentaje total de carga; también actualiza el valor de la barra de progreso mostrada al usuario. Si la carga es menor al 100% esta función se llamará a si misma hasta haber completado la carga. En caso de haber alcanzado el 100% calcularProgreso() llamará a finCarga().
  • finCarga(): llamada por calcularProgreso() al alcanzar el 100% de la carga de las imágenes. Esta función contendrá código definido por el programador para realizar un proceso adecuado al contexto del sistema. Para este ejemplo simplemente se muestra un alert() informando que las carga ha sido completada.
  • mostrarImagen(): esta función la he colocado para que las imágenes se vayan mostrando en el navegador a medida que su carga se complete. Es simplemente a modo de ejemplo... el programador luego decidirá si las imágenes deben mostrarse al cargarse o se mostrarán más tarde cuando se ejecute un evento determinado.

Les dejo el código fuente para que lo examinen:

JavaScript:
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  5. <title>Precarga de imágenes con Barra de Progreso</title>
  6. <script type="text/javascript">
  7. // Ruta de las imagenes que se van a cargar
  8. var cargar=new Array("1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg", "6.jpg", "7.jpg", "8.jpg");
  9. // Leyenda que aparecerá en la capa leyenda
  10. var leyenda="Cargando imágenes";
  11. // Frecuencia de actualización de la barra de progreso en milisegundos
  12. var frecuencia=100;
  13. // Cada cuantas actualizaciones de la barra de progreso se desea que cambie la leyenda
  14. var cambioLeyenda=10;
  15.  
  16. // Similar a <body onload="cargar()">
  17. window.onload=iniciar;
  18.  
  19. function iniciar()
  20. {
  21.     imagenes=new Array();
  22.     // Recorro el array donde definí las rutas de las imagenes
  23.     for(i=0; i<cargar.length; i++)
  24.     {
  25.         // Creo un nuevo elemento img
  26.         imagenes[i]=document.createElement("img");
  27.         // Le asigno el atributo src. Con esto alcanza para que el navegador cargue la imágen, aunque ésta no se muestre
  28.         imagenes[i].src=cargar[i];
  29.     }
  30.    
  31.     divCompletado=document.getElementById("barraCompletado");
  32.     divPorcentaje=document.getElementById("barraPorcentaje");
  33.     divLeyenda=document.getElementById("leyenda");
  34.     // Variable para monitorear la cantidad de veces que se ejecuta calcularProgreso(). Se utiliza para cambiar la leyenda
  35.     cantEjecuciones=0;
  36.     // Esta variable será la responsable de colocar puntos suspensivos en movimiento detrás de la leyenda declarada previamente
  37.     leyendaActual=leyenda;
  38.     // Cantidad de puntos suspensivos que debo colocar detrás de la leyenda. Esta variable se irá incrementando hasta llegar a 3. Luego se pondrá en 0 nuevamente
  39.     puntitos=0;
  40.    
  41.     // Llamo a calcularProgreso para colocar la barra, leyenda y porcentaje en su estados correspondientes
  42.     calcularProgreso();
  43. }
  44.  
  45. function calcularProgreso()
  46. {
  47.     // Variable que reflejará el porcentaje actual de carga
  48.     var porcentajeActual=0;
  49.     var i=0;
  50.     // Variable para contar la cantidad de imágenes completamente cargadas del total
  51.     var cantImagenesCompletadas=0;
  52.     // Incremento la cantidad de ejecuciones de esta función
  53.     cantEjecuciones++;
  54.  
  55.     if(cantEjecuciones==cambioLeyenda)
  56.     {
  57.         // Si en la última actualización se colocaron 3 puntos suspensivos, ahora no se colocará ninguno
  58.         if(puntitos==3) puntitos=0;
  59.         else puntitos++;
  60.        
  61.         leyendaActual=leyenda;
  62.  
  63.         cantEjecuciones=0;
  64.        
  65.         // Con este while coloco los puntos suspensivos detrás de la leyenda. Se colocarán tantos puntos como diga la variable puntitos
  66.         while(i<puntitos)
  67.         {
  68.             leyendaActual+=".";
  69.             i++;
  70.         }
  71.     }
  72.    
  73.     // En este for recorro el array de los elementos img y pregunto cuales de ellos han terminado de cargarse
  74.     for(i=0; i<imagenes.length; i++)
  75.     {
  76.         // Por cada imágen cargada incremento la variable cantImagenesCompletadas
  77.         if(imagenes[i].complete)
  78.         {
  79.             cantImagenesCompletadas++;
  80.             mostrarImagen(imagenes[i]);
  81.         }
  82.     }
  83.     // Calculo el porcentaje actual de carga con una regla de 3 en base a la cantidad de imágenes totales y las ya cargadas y rendondeo sin decimales
  84.     porcentajeActual=Math.ceil(cantImagenesCompletadas*100/cargar.length);
  85.    
  86.     // Reflejo los cambios en las capas que corresponda
  87.     divLeyenda.innerHTML=leyendaActual;
  88.     divPorcentaje.innerHTML=porcentajeActual+"%";
  89.     divCompletado.style.width=porcentajeActual+"%";
  90.    
  91.     // Si el porcentaje de carga es distinto 100 vuelvo a llamar a esta misma función con setTimeout
  92.     if(porcentajeActual==100) finCarga();
  93.     else setTimeout("calcularProgreso()", frecuencia);
  94. }
  95.  
  96. function finCarga()
  97. {
  98.     // Acciones a realizar cuando se finalizó la carga de todas las imágenes
  99.     divLeyenda.innerHTML="Carga completa";
  100.     alert("Carga completa");
  101. }
  102.  
  103. function mostrarImagen(imagen)
  104. {
  105.     var capa=document.getElementById("mostrar");
  106.     capa.appendChild(imagen);
  107. }
  108. </script>
  109.  
  110.  
  111. <style type="text/css">
  112. #barraTotal
  113. {
  114.     position:relative;
  115.     width:200px;
  116.     height:30px;
  117.     background-color:#000000;
  118. }
  119.  
  120. #barraCompletado
  121. {
  122.     position:absolute;
  123.     top:0; left:0;
  124.     width:1%;
  125.     /* height se expresa en px y no en % porque el IE6 tiene algún problema extraño actualizando el div expresado en porcentaje */
  126.     height:30px;
  127.     background-color:#999999;
  128. }
  129.  
  130. #barraPorcentaje
  131. {
  132.     position:absolute;
  133.     top:5px; left:5px;
  134.     color:#FFFFFF;
  135.     font-weight:bold;
  136. }
  137.  
  138. .esconder
  139. {
  140. visibility:hidden;
  141. }
  142. </style>
  143. </head>
  144.  
  145. <body>
  146. <div id="contendor">
  147.     <div id="leyenda"></div>
  148.     <div id="barraTotal">
  149.         <div id="barraCompletado"></div>
  150.         <div id="barraPorcentaje"></div>
  151.     </div>
  152. </div>
  153. <div id="mostrar"></div>
  154. </body>
  155. </html>

Nada más por ahora, cualquier duda comenten.
Saludos.