7.- CSS DINAMICAS.

En este apartado estudiaremos el funcionamiento de ejemplos más o menos complejos (y más o menos espectaculares) y analizaremos en profundidad el código que hace posible esas animaciones o efectos.

Veremos cinco ejemplos (en algunos de ellos comentaremos más de un ejemplo), en los cuales, haremos una introducción para después pasar a ver las definiciones y el código.




7.1.- MOVIMIENTO CIRCULAR DE OBJETOS.

Cualquier movimiento de objetos, ya sean bloques de texto, imágenes, etc, en una página HTML es un efecto que puede llegar a ser espectacular.

En los dos ejemplos que veremos a continuación hacemos uso del movimiento en círculo para mover ciertos objetos. No es nada extraordinario, pero acostumbrados a páginas estáticas, éstas pueden resultar curiosas.

El primer ejemplo que nos ocupa será una "simulación" de una órbita de un planeta alrededor de una estrella.

Tendremos tres imágenes en pantalla: el sol, la luna y la tierra, todas ellas con posición absoluta, y una función que periódicamente será ejecutada y se encargará de calcular la posición de la tierra y la luna respecto a ésta.

Ejecutar el ejemplo...

<HTML>
<HEAD>
<TITLE>Sistema Planetario</TITLE>

<STYLE TYPE="text/css">
#sol {
  position: absolute;
  top:  200;
  left: 350;
}

#planeta {
  position: absolute;
  top:  200;
  left: 490;
}

#luna {
  position: absolute;
  top:  216;
  left: 556;
}
</STYLE>


</HEAD>
<BODY BGCOLOR="#000000" BACKGROUND="stars.gif" >


<SPAN ID=sol><img src=sun.gif></SPAN>
<SPAN ID=planeta><img src=earth.gif></SPAN>
<SPAN ID=luna><img src=moon.gif></SPAN>


<SCRIPT>
  Xi     = 300;
  Yi     = 200;
  radiop = 190; 
  radiol = 50;
  inc    = Math.PI/130
  ang = 0;

  function mover() {
        x_planeta = (radiop * Math.cos(ang)) + Xi;
        y_planeta = (radiop * Math.sin(ang)) + Yi;

        x_luna    = x_planeta + 16 + radiol*Math.cos(6*ang);
        y_luna    = y_planeta + 16 + radiol*Math.sin(6*ang);

        document.planeta.left = x_planeta;
        document.planeta.top  = y_planeta;
        document.luna.left    = x_luna;
        document.luna.top     = y_luna;

        ang+=inc;
        if ( ang >= 2*Math.PI ) ang = 0;

        setTimeout("mover()", 20);
  }

  setTimeout("mover()", 20);
</script>

</BODY>
</HTML>


El segundo ejemplo es una página en la que un logotipo se desplaza hacia abajo y los links giran alrededor del logo. Como añadidura, cuando el puntero pasa sobre un link, un mensaje aparece en el centro de la página, como cuando hacemos un window.status="mensaje".

Este otro ejemplo, al estar hecho para guardar la compatibilidad con E4, es más complejo de entender, pero básicamente, hace lo mismo que el anterior: define varios layers que serán cada objeto (links, tips, logo) y después los mueve por la pantalla siguiendo las ecuaciones anteriores. Para mostrar/ocultar los tips, se utilizan dos funciones a las que se les pasa el objeto y se cambia la propiedad visibility.

Para guardar la compatibilidad, se hacen uso de las técnicas vistas en el tema de INCOMPATIBILIDADES (detectar el nombre y versión del navegador utilizado, determinar el D.O.M. soportado, usar variables de referencia a los layers, etc).

Ejecutar el ejemplo...

Para ver el código del ejemplo, utilizar la opción del navegador View Page Source (ver código fuente de la página).




7.2.- AJUSTAR TAMAÑOS DE BLOQUES.

En los siguientes dos ejemplos nos centraremos en la captura de eventos para hacer la redimensión de un layer dinámicamente, esto es, una vez cargada la página, mediante la interacción del ratón, hacer que un layer cambie de tamaño.

En la página sólo definimos un layer que incluye la página HTML:

   <LAYER NAME="layer1" LEFT=100 WIDTH=300 BGCOLOR="#99bbFF"
      SRC="inc1.htm" >
   </LAYER>
En el código JS que hace posible la redimensión capturamos primeramente los eventos MOUSEUP y MOUSEDOWN.
   layer1.document.captureEvents(Event.MOUSEUP|Event.MOUSEDOWN|Event.MOUSEDRAG);
   layer1.document.onmousedown=begindrag;
   layer1.document.onmouseup=enddrag;
Después, ante un evento MOUSEDOWN pasamos a manejar también los eventos de movimiento de ratón.
   function begindrag(e) {
    layer1.document.captureEvents(Event.MOUSEMOVE);
    layer1.document.onmousemove=drag;
    oldX=e.pageX;
    return false;
   }
Ante un evento MOUSEMOVE cambiamos el tamaño del layer (cargando la página HTML que incluye).
   function drag(e) {
    changeWidth(layer1, e.pageX - oldX);
    oldX = e.pageX;
    return false;
   }

   function changeWidth(layer, delta) {
    layerWidth = layerWidth + delta;
    if (delta != 0)
    layer.load("mytext.htm", layerWidth);
   }
Ante un evento MOUSEUP dejamos de manejar los eventos de movimiento del ratón.
   function enddrag(e) {
    layer1.document.onmousemove=0;
    layer1.document.releaseEvents(Event.MOUSEMOVE);
    return false;
   }

Ejecutar el ejemplo...

Para ver el código del ejemplo, utilizar la opción del navegador View Page Source (ver código fuente de la página).



Otro ejemplo relacionado con la redimensión es el que pasamos a esbozar a continuación: expandir los cuatro cuadrados, en el que aparecen cuatro cuadrados de colores en los que se muestra un número. Si colocamos el ratón sobre algún cuadrado, éste comienza a crecer hasta un tamaño máximo. Una vez alcanzado ese tamaño, al colocarle el ratón encima, comenzará a decrecer hasta su tamaño mínimo.

En principio los layers se crean de 200x200, pero cuando terminan de ser cargados, se ajusta su tamaño a 50x50 y se asignan el fichero HTML que se verá en el layer y el texto que se verá cuando esté contraido.

Hay dos funciones definidas para controlar las expansiones y contracciones de los layers, impidiendo que se responda a eventos de ratón mientras está expandiéndose o contrayéndose (expand(n) y contract(n)).

Ejecutar el ejemplo...

Para ver el código del ejemplo, utilizar la opción del navegador View Page Source (ver código fuente de la página).




7.3.- DRAG & DROP.

Una aplicación muy vistosa de los nuevos manejadores de ejemplos es la posibilidad de hacer drag&drop.

El ejemplo que nos ocupa trata de hacer un sistema de ventanas al estilo Windows95 y similares dentro de una página Web.

El truco en este caso es definir una serie de layers (uno por ventana) de forma que los "adornos" (léase botones, barra de título, etc) son otros layers hijos del principal. Habrá un layer principal gris, que dará soporte al resto, así, cuando movamos este, todos van junto con él.

Como hijos de este layer soporte, están los de título, botones y el de contenido, que muestra el fichero HTML que vamos a ver en la "ventana".

Para hacer el drag&drop, tenemos que: cuando se pulse sobre el layer de título y se mueva el ratón, se debe desplazar el layer de soporte hasta que se suelte el botón; cuando se pulse sobre el layer de contenido y se mueva el ratón, se debe redimensionar el layer de soporte; cuando se pulse sobre el botón de cerrar, se debe hacer invisible.

En cuanto a los eventos a capturar, tenemos que: los layers de título, soporte y el botón de cerrar deben tratar el MOUSEDOWN; los layer de título y soporte deben tratar el MOUSEUP.

Debido a la jerarquía utilizada en el tratamiento de eventos, el layer de soporte, al contener a los otros, recibe los eventos y si decide no tratarlos, entonces los pasa a los otros layers para que los traten. Pero en este problema no nos interesa que él los trate primero, sino que queremos que los traten primero los otros layers y después él. Así que deberemos hacer que los eventos pasen la capa jerárquica para ver si la siguiente trata el evento o en otro caso, lo trata. Esto lo haremos con la función routeEvent(e), del siguiente modo:

	function beginresize(e) {
	    var retval=soporte.document.routeEvent(e)
	    if (retval==true) 
	        return false;

	    soporte.document.captureEvents(Event.MOUSEMOVE);
	    soporte.document.onmousemove=resizedrag;
	    oldX=e.pageX;
	    return false;
	}
	
Ejecutar el ejemplo...

Para ver el código del ejemplo, utilizar la opción del navegador View Page Source (ver código fuente de la página).




7.4.- HACER SCROLL EN LOS BLOQUES.

Ya dijimos que en E4, como utilizaba FRAMES para hacer la carga de documentos en los layers, podíamos indicar si queríamos permitir el scroll en el layer o no. Sin embargo, en N4, si queremos hacer scroll del contenido de un layer, debemos programarlo nosotros solos.

En este ejemplo veremos una forma de hacer el scroll en un layer.

La idea viene a ser bastante simple: definir un layer contenedor dentro del cual se definen otros que serán de los que se haga scroll (layers de contenido), y según unos controles, mover esos layers de contenido arriba o abajo dentro del layer contenedor un cierto número de pixels.

Deberemos definir varios layers, unos para hacer de soporte y otros para hacer las veces de flechitas de sube-baja (e incluso otro para la barra de scroll) y para elegir el texto o elemento que vamos a visualizar en el scroll.

Así pues, definiremos un layer principal para contener a todo el resto de layers (elementos a visualizar, elementos de control, etc). Dentro de éste definimos otro para seleccionar el elemento a visualizar, otro que nos servirá como apoyo a todos los layers-contenido y finalmente otro que contendrá los controles de subir y bajar.

La función principal para hacer el scroll se limitará a comprobar si hay eventos de ratón (MOUSEDOWN) o en caso contrario no hará nada. Si sí los hay, calcula si está o no en el tope superior (el tope inferior se especifica mediante una variable global). Sólo debe mover el texto si no está arriba del todo o abajo del todo, y el movimiento es simplemente incrementar o decrementar las coordenadas verticales del layer de contenido.

El cógido de la función que hace esto es el siguiente:

	function scroll(direction) {
	    if (scrollActive) {
        	if (n) 
	          var top = eval("document.principal.document.elementos.document." +
	                        scrollContentShown + ".top")
	        if (ie) 
	          var top = eval(scrollContentShown + ".style.pixelTop") 

	        if (direction == "up" && top < 0) {    // ver si ya esta arriba del todo
	          var inc = 10                         // mover de 10 en 10 px
        	  if (n) 
	            eval("document.principal.document.elementos.document." +
	                        scrollContentShown + ".top += inc")
        	  if (ie) 
	            eval(scrollContentShown + ".style.pixelTop += inc")

        	  setTimeout("scroll('up')",20)
	        }

	        if (direction == "down" && top > scrollLimit) {  // ver si ya esta abajo del todo
        	  var inc = -10   // mueve de 10 en 10 px
	          if (n) 
        	     eval("document.principal.document.elementos.document." +
	                        scrollContentShown + ".top += inc")
	          if (ie) 
        	    eval(scrollContentShown + ".style.pixelTop += inc")

	          setTimeout("scroll('down')",20)
        	}
	    }

	}
	

Ejecutar el ejemplo...

Para ver el código del ejemplo, utilizar la opción del navegador View Page Source (ver código fuente de la página).




7.5.- OTROS EJEMPLOS.

En este último punto, veremos varios ejemplos más que comentaremos si tenemos tiempo...

En el primer ejemplo veremos técnicas para hacer movimientos sencillos así como para mantener distintos planos de imágenes en una misma página.

Se trata de una imágen que se desplaza de izquierda a derecha, entre dos puntos prefijados, a una velocidad fija, y que en su camino tiene otras imágenes que se encuentran en planos diferentes, tanto por encima como por debajo. La primera imagen, al pasar por la zona donde están las otras imágenes, aparece como si estuviese por delante o por detrás de las otras (como en diferentes planos).

En este ejemplo, el "truco" está en definir cada imagen en un layer diferente y establecer las propiedades z-index de los layers de forma adecuada para que cada uno quede en un plano diferente.

Por último, cuando la página haya sido cargada, se inicia la animación. La función JS que la realiza es muy sencilla:

	function mover() {
	    var fish = document.fish;
	    if (fish.left < 400) {
	        fish.moveBy(5, 0);}
	    else {fish.left = 10;}

	    setTimeout("mover()", 10);
	    return;
	}
	
Ejecutar el ejemplo...

Para ver el código del ejemplo, utilizar la opción del navegador View Page Source (ver código fuente de la página).



En este ejemplo podremos ver técnicas para hacer movimientos preestablecidos y también para dejar un mensaje de espera mientras cargamos las imágenes. Otra cosa interesante en el ejemplo es el uso de la versión del lenguaje en el tag SCRIPT, en este caso, se utiliza la versión de Microsoft JSCRIPT para hacer compatible el código.

Ejecutar el ejemplo...

Para ver el código del ejemplo, utilizar la opción del navegador View Page Source (ver código fuente de la página).

 
Pedro Angel Castillo Valdivieso: pedro@geneura.ugr.es
Fco. Javier García Castellano: fjgc@decsai.ugr.es
Equipo GeNeura
Departamento de Arquitectura y Tecnología de los Computadores
Universidad de Granada
tlf: +34-58-243163
fax: +34-58-243230