jQuery Blues: 8. Animaciones personalizadas

En esta entrada veremos cómo crear nuestras propias animaciones y aprenderemos a guardar selectores en variables.

klimt

archivado en: JavaScript / 3 diciembre, 2012 / taller:

En la entrada anterior de esta serie vimos cómo realizar varios efectos «prefabricados», pero jQuery también permite preparar efectos a medida mediante el método .animate(). Su sintaxis más sencilla es:

  • .animate({ propiedad }, opciones )

Propiedades

En el primer argumento se indica cuál es la propiedad CSS que se quiere modificar, como la opacidad (opacity), el ancho y el alto (width, height), la fuente (font) o la posición (left, rigth, top, bottom); aunque algunas propiedades, como el color de fondo (background-color) aún no se pueden modificar directamente con .animate().

Además, se pueden modificar dos propiedades que no existen en las CSS y son propias de jQuery: scrollTop y scrollLeft.

Cada propiedad que se va a animar se especifica con un par propiedad:valor.

  • jQuery('selector').animate({
  • opacity: 0.5 ...

Hay un tipo de valor especial: +=/-=. Cuando se indica un valor con el signo + o - seguido del signo =, toma como valor el que ya tiene más o menos el indicado. Por ejemplo, esto:

  • jQuery('selector').animate({
  • opacity: 0.5,
  • left: '+=50' ...

mueve el selector 50 píxeles a la izquierda a partir de su coordenada actual. (De todas maneras, esto solo se necesita para animaciones muy complejas y normalmente con definir el valor de forma normal es más que suficiente, esto es, left:50).

Importante: como ocurre con las CSS, para mover un elemento con top, left, right o bottom, tiene que tener definido position:relative o position:absolute en la hoja de estilo.

Si se modifica más de una propiedad, se especifican separadas entre sí por comas. Por ejemplo:

  • jQuery('selector').animate({
  • opacity: 0.5,
  • left: 50,
  • font: '#900'
  • }, 1500 );

En algunas propiedades, además de los valores numéricos, podemos especificar que la animación sea 'show' (mostrar), 'hide' (ocultar) o 'toggle'. Por ejemplo, si indicamos height: 'hide', el elemento irá perdiendo el alto hasta desaparecer. Toggle funciona como siempre, es decir, calcula si se ha pulsado o no previamente para ocultar o mostrar algo. Por ejemplo, este script ocultaría el div al pulsar el párrafo por primera vez y lo mostraría la segunda.

  • ...
  • jQuery(document).ready(function($) {
  • jQuery("p").click (function () {
  • jQuery('#selector').animate({
  • opacity: 0.5,
  • left: 50,
  • font: '#900',
  • height: 'hide'
  • }, 1500 );
  • });
  • });
  • </script>
  • ...
  • <p>oculta</p>
  • <div id="selector">
  • Ejemplo animate
  • </div>
  • ...

Opciones

En el segundo argumento se especifican diversas opciones, cada una formada por un par opción-valor separados entre sí por comas (aunque a veces no hace falta especificar el nombre de la opción). El argumento más importante es duration, que especifica el tiempo en milisegundos o con las cadenas de texto 'slow' y 'fast' que durará la animación. Es la única opción imprescindible.

  • jQuery(document).ready(function($) {
  • jQuery('#selector').animate({
  • opacity: 0.1
  • }, duration: 1500 );
  • });

Con duration ya podemos diseñar nuestras propias animaciones, pero también tenemos otras opciones disponibles, que son:

easing: una cadena de texto en la que se especifican un tipo de transiciones especiales predefinidas, como linear. Esto guarda relación con un añadido de jQuery llamado jQueryUI, que ya veremos en otro momento.

complete: se llama a una función una vez que ha concluido la animación. Es algo parecido al callback de funciones que veíamos en la entrada anterior.  Por ejemplo, así bajaríamos la opacidad del párrafo del ejemplo de antes una vez que ha concluido la animación que afecta al div con id selector.

  • $.noConflict();
  • jQuery(document).ready(function($) {
  • jQuery("p").click (function () {
  • jQuery('#selector').animate({
  • opacity: 0.5,
  • left: 50,
  • font: '#900',
  • height: 'hide'
  • }, 1500, function() {
  • jQuery("p").animate({
  • opacity: 0.5
  • });
  • });
  • });
  • });

Hay alguna opción más, como step o specialEasing, pero vamos a dejar aquí la teoría para hacer una práctica.

Práctica: diapositivas

Nos faltan por tratar otras maneras de seleccionar nodos, como los filtros, pero tanto para las que ya conocemos como para las que veremos rige el mismo principio: para que el jQuery de una página se procese con rapidez, hay que trabajar con IDs.

Esto se entiende bien si pensamos que algunas páginas pueden tener cientos de líneas de código, incluso miles si son muy complejas. Cuando jQuery busca un elemento recorriendo el documento DOM tiene que «leerlas» todas hasta que encuentra el nodo indicado y eso es mucho más lento que si busca directamente un ID, ya que, acordémonos, los identificadores son únicos. Es decir, el nombre de un ID debe ser distinto y único para cada elemento.

  • <h3 id="soy un id que no se puede repetir en todo el documento" class="soy una clase que da igual si se repite"> Tararí, tarará </h3>

Entonces, cuando no podamos referirnos a un nodo directamente por su ID, porque no lo tiene o la razón que sea, al menos sí es recomendable indicar en el contexto del selector el ID inmediatamente superior, de forma parecida a como hacíamos con this. Este galimatías se entiende bien con un ejemplo.

Imaginemos que tenemos el siguiente documento:

  • ...aquí hay muchas líneas de código antes...
  • <div id="desarrollo">
  • <p> Soy un párrafo </p>
  • <p> Soy otro párrafo párrafo </p>
  • <aside> Soy un aside </aside>
  • </div>
  • <div id="desarrollo2">
  • <p> Soy un párrafo </p>
  • <p> Soy otro párrafo párrafo </p>
  • <aside> Soy un aside </aside>
  • </div>
  • ...aquí hay muchas líneas de código después...

Los dos asides no tienen identificador, pero se encuentran entre divs que sí lo tienen, así que podríamos seleccionarlos poniendo como contexto este id, igual que hacíamos con this:

Así para el primero:

  • jQuery("aside", "#desarrollo").css("border","9px solid red");

Y así para el segundo:

  • jQuery("aside", "#desarrollo2").css("border","9px solid red");

Pero, como decía, es aún mejor referenciar directamente el ID y aquí vamos a ver un truco muy chulo, aunque antes debemos saber o recordar dos cosas.

Primera, las cadenas de texto se pueden concatenar (sumar) mediante el operador + (hay otras formas, pero de momento solo nos interesa esta). Por ejemplo, si tenemos estas dos variables:

  • var SoyUnaVariable = "Los gatos son... ";
  • var SoyOtraVariable =" ...formidables";

podemos concatenarlas en una tercera variable:

  • var TerceraVariable = SoyUnaVariable + SoyOtraVariable;

que valdrá la cadena de texto  "Los gatos son...  ...formidables".

Y lo segundo que debemos saber para esta práctica es que muchas etiquetas de HTML tienen atributos con información complementaria. Por ejemplo, la etiqueta <img> puede tener el atributo alt, que sirve para describir el contenido de una imagen.

<img src="mi_imagen.jpg" alt="descripción de la imagen">

De hecho, class e id son precisamente eso, atributos. Y aquí empieza lo bueno, pues con jQuery es muy fácil saber el valor de un atributo mediante el método attr('atributo').

Por ejemplo, esto recuperaría el atributo title de una imagen:

  •  jQuery("img").attr("title");

Y esto el id del primer párrafo del ejemplo anterior

  •  jQuery("#desarrollo").attr("id");

Es decir, esa sentencia devolvería «desarrollo».

Claro está, este valor se puede almacenar en una variable  🙂

  • var id_del_div = jQuery("#desarrollo").attr("id");

Bueno, pues con estas dos cosas —concatenando variables y sacando el id de un nodo— ya podemos hacer una práctica divertida. Vamos a preparar una especie de pase de diapositivas de imágenes. En la parte superior habrá una serie de miniaturas y, al pulsarlas, se desplegará la respectiva imagen en grande. Algo así...

[singlepic id=33 w=422 h=433 float=center]

El código HTML es sencillo. En un nav incluimos las miniaturas, flotadas a la izquierda, y en un div ponemos las imágenes grandes.

  1. ...
  2. <style type="text/css">
  3. #wrap {
  4. margin:0 auto;
  5. width:600px;
  6. }
  7. #barra_imagenes {
  8. overflow:hidden;
  9. display:block;
  10. }
  11. .miniaturas img {
  12. width:75px;
  13. height:56px;
  14. float:left;
  15. margin:0.5em;
  16. }
  17. </style>
  18. ...
  19. <div id="wrap">
  20. <nav id="barra_imagenes">
  21. <div class="miniaturas" id="min1">
  22. <img src="img01.jpg">
  23. </div>
  24. <div class="miniaturas" id="min2">
  25. <img src="img02.jpg">
  26. </div>
  27. <div class="miniaturas" id="min3">
  28. <img src="img03.jpg">
  29. </div>
  30. <div class="miniaturas" id="min4">
  31. <img src="img04.jpg">
  32. </div>
  33. </nav>
  34. <br />
  35. <div id="muestra_diapositivas">
  36. <img src="img01.jpg" id="min1_grande">
  37. <img src="img02.jpg" id="min2_grande">
  38. <img src="img03.jpg" id="min3_grande">
  39. <img src="img04.jpg" id="min4_grande">
  40. </div>
  41. </div>
  42. ...

Observad que en las imágenes grandes, el id está formado por el id de la miniatura (min1) más la cadena de texto «_grande».

Vamos primero a armar todo el proceso y luego ya añadimos alguna animación chula. Entonces, lo primero es ocultar todas las imágenes grandes, menos la primera, cuyo id vamos a guardar en una variable para luego utilizarla como selector.

  1. <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
  2. <script type="text/javascript">
  3. $.noConflict();
  4. jQuery(document).ready(function($) {
  5. // al cargar ocultamos todas las imágenes
  6. jQuery ("img", "#muestra_diapositivas").hide();
  7. // menos la primera
  8. var IdImagenVista = "#min1_grande";
  9. jQuery (IdImagenVista).show();
  10. });
  11. </script>

Y ahora viene lo chulo: vamos ocultando y mostrando la imagen grande recuperando el atributo id de la miniatura pulsada y utilizándolo como selector tras haberle añadido la cadena de texto "_grande".

  1. <script type="text/javascript">
  2. $.noConflict();
  3. jQuery(document).ready(function($) {
  4. // al cargar ocultamos todas las imágenes
  5. jQuery ("img", "#muestra_diapositivas").hide();
  6. // menos la primera
  7. var IdImagenVista = "#min1_grande";
  8. jQuery (IdImagenVista).show();
  9. // al pulsar en una miniatura, mostramos su imagen grande
  10. jQuery(".miniaturas", this).click(function () {
  11. // primero ocultamos la imagen que está descubierta
  12. jQuery (IdImagenVista).hide();
  13. // Cambiamos el valor de la variable. Primero recupramos el id:
  14. var id_visible = jQuery(this).attr("id");
  15. // Y ya cambiamos el valor añadiendo la almohadilla y la cadena _grande
  16. IdImagenVista = '#'+id_visible+"_grande";
  17. // Por último, mostramos la imagen grande correspondiente
  18. jQuery (IdImagenVista).fadeIn("slow");
  19. });
  20. });
  21. </script>

Una vez comprendido el proceso, es decir, cómo podemos ir definiendo selectores al vuelo jugando con las variables, podemos complicar un poco el script anterior añadiendo una animación en las miniaturas, para que se baje la opacidad de la que está pulsada.

  1. <script type="text/javascript">
  2. $.noConflict();
  3. jQuery(document).ready(function($) {
  4. // al cargar, inicializamos las variables
  5. var IdImagenVista = "#min1_grande";
  6. var IdMiniaturaActiva ="#min1";
  7. var id_visible;
  8. // ocultamos todas las imágenes
  9. jQuery ("img", "#muestra_diapositivas").hide();
  10. // menos la primera
  11. jQuery (IdImagenVista).show();
  12. // bajamos la opacidad de la primera miniatura
  13. jQuery (IdMiniaturaActiva).animate({
  14. opacity: 0.25
  15. }, 100 );
  16. // Al pulsar una miniatura
  17. // Mostramos su imagen grande
  18. jQuery(".miniaturas", this).click(function () {
  19. // subimos la opacidad de la miniatura activa
  20. jQuery (IdMiniaturaActiva).animate({
  21. opacity: 1
  22. }, 900 );
  23. // le bajamos la opacidad a esta
  24. jQuery (this).animate({
  25. opacity: 0.25
  26. }, 900 );
  27. // primero ocultamos la imagen que está descubierta
  28. jQuery (IdImagenVista).hide();
  29. // Cambiamos el valor de la variable. Primero recuperamos el id:
  30. id_visible = jQuery(this).attr("id");
  31. // Y ya cambiamos el valor añadiendo la almohadilla y la cadena _grande
  32. IdImagenVista = '#'+id_visible+"_grande";
  33. // Mostramos la imagen grande correspondiente
  34. jQuery (IdImagenVista).fadeIn("slow");
  35. // Guardamos su id para recuperar su opacidad cuando vuelvan a pulsar
  36. IdMiniaturaActiva = '#'+id_visible;
  37. });
  38. });
  39. </script>

Bueno, esta entrada es la más complicada de lo que llevamos visto hasta ahora, pero si conseguimos entenderla podremos trabajar directamente con IDs, lo cual hará que nuestro código sea mucho más rápido. En cualquier caso, espero que las siguientes sean más sencillas.

Una práctica para terminar. Mediante un alert

  • alert(NombreVariable);

cuando el documento esté cargado, mostrar el valor de NombreVariable, el cual debe ser resultado de sumar dos identificadores distintos, cada uno de un párrafo.

|| Tags: , ,

valoración de los lectores sobre jQuery Blues: 8. Animaciones personalizadas

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • 4.6 sobre 5 (10 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

2 respuestas a “jQuery Blues: 8. Animaciones personalizadas

  1. Marcos un saludo desde Colombia, he realizado todo el tutorial de jQuery hasta ahora y voy super bien, explicas muy claro y las practicas que dejas sirven de mucho para repasar lo aprendido. Espero que este tuto no sea el ultimo y sigue para adelante que lo haces muy bien, gracias!

  2. marcos el dijo:

    Muchas gracias Charles.

    No, no será el último, pero es que llevo un par de semanas con mucho trabajo y no consigo sacar tiempo para el blog.

    Un fuerte abrazo.