Ir directamente al contenido de esta página

Carrusel con desplazamiento horizontal, en menos de 2… en lo menos que hemos podido

Como hicimos hace tiempo, queríamos replicar un efecto de animación de JavaScript para un carrusel de imágenes muy común en un script que pesase menos de 2Kb. Por mucho que lo hemos intentado no hemos sido capaces de reducir el peso hasta ese tamaño, pero aún así nuestro código sigue siendo ligero y útil.

En concreto, queríamos reproducir el efecto de carrusel con desplazamiento horizontal que se ve en la página de inicio de muchos sitios web, una interfaz con la que el usuario puede desplazarse entre tres o cuatro «diapositivas» que resumen el mensaje principal que se quiere transmitir. Nosotros mismos en nuestra página de EidoWeb empleamos uno, aunque ahí se trata de un plugin para JQuery, jCarousel Lite.

Cuestiones previas

Imaginarse la mecánica no es difícil: el carrusel no consiste más que en una serie de elementos flotados uno al lado de otro, dispuestos dentro de un contenedor que sólo permite ver uno de ellos, y una animación que vaya desplazando hacia la derecha o la izquierda la «tira» de imágenes adyacentes.

Sin embargo, había dos puntos que no todos los plugins que logran este efecto solucionan de manera satisfactoria, y que teníamos que tener en cuenta antes de ponernos a programar:

  1. No siempre se puede especificar el ancho inicial de los elementos que se van a convertir en las diapositivas del carrusel.
  2. El carrusel no siempre va a contener imágenes en exclusiva, por lo que tampoco se puede especificar la altura.

Con respecto al primero, es muy común que el programador del plugin considere que el contenido va a consistir en una lista de imágenes de idénticas proporciones, y que por ello asigne el ancho especificado para las imágenes como el ancho de las diapositivas. Sin embargo, puede ser que el diseño en el que se haya incluido la imagen sea un diseño fluido, y que por lo tanto se den dos situaciones:

En ambos casos, no se puede definir inicialmente el ancho de la imagen. Esto ocurría por ejemplo con Easy Slider 1.7, que modificamos en su momento para hacerlo fluido.

Con respecto al segundo punto, está relacionado con el anterior. Cuando el contenido de las diapositivas es una imagen, se podría especificar la altura de la misma, pero cuando se trata de un contenido que incluye texto…

Como se ve en el ejemplo, las alturas de los contenidos de las diapositivas no coinciden

…la altura depende de la cantidad de contenido y del tamaño de fuente del usuario, así que volvemos a tener el problema de no saber qué valor asignar.

Nuestro script

En el código hemos reutilizado parte de nuestro scrollTo para la mecánica de la animación, así que no es necesario comentarlo aquí línea a línea. Lo que hace nuestro código es, una vez que ha asignado el ancho a cada elemento de la lista y al visor, compara las alturas resultantes de cada diapositiva y asigna a cada una de ellas la altura máxima; por último simplemente crea el contador y los controles de desplazamiento.

Helo aquí:


var CH = {
  ds: '',
  dA: 0,
  sD: 0,
  tD: 0,
  an: 0,
  fotogramas: [1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1],
  idD: 'diapos',
  nID: 'diapos-on',
  idC: 'contador',
  idCn: 'controles',
  clC: 'actual',
  intv: '',
  act: true,
  $ : function(id){var elem = document.getElementById(id);return elem;},
  ac: function(c){CH.$(CH.idC).getElementsByTagName('li')[CH.dA].className=c;},
  desp: function(x){
    if(CH.act==true){
      if(((x==-1)&&(CH.dA!=CH.tD))||((x==1)&&(CH.dA!=0))){
        CH.act = false;
        var pos = 0; 
        CH.intv = setInterval(function(){
          if(pos<CH.fotogramas.length){
            var inicio = parseInt(CH.$(CH.idD).style.left.replace('px',''));
            CH.$(CH.idD).style.left = (inicio+(Math.round(CH.an*(CH.fotogramas[pos]/100))*x))+'px';
            pos++;
          } else {
            CH.ac('');
            (x==-1) ? CH.dA++ : CH.dA--;
            CH.$(CH.idD).style.left = ((CH.an*CH.dA)*(-1))+'px';
            CH.ac(CH.clC); 
            pos = 0; 
            CH.act = true;
            clearInterval(CH.intv);
          } 
        },50);
      }
    }
  },
  dims : function(){
    var alF=0;
    CH.an = (CH.$(CH.nID).offsetWidth) ? CH.$(CH.nID).offsetWidth : CH.$(CH.nID).style.pixelWidth;
    for(var i=0;i<=CH.tD;i++){
      var al = (CH.ds[i].offsetHeight) ? CH.ds[i].offsetHeight : CH.ds[i].style.pixelHeight;
      (al>alF) ? alF = al : alF = alF;
    }
    CH.$(CH.nID).setAttribute('style','height:'+alF+'px;width:'+CH.an+'px;position:relative;overflow:hidden;');
    CH.$(CH.idD).setAttribute('style','height:'+alF+'px;width:'+(CH.an*CH.ds.length)+'px;position:absolute;top:0;left:0;'); 
    for(var i=0;i<=CH.tD;i++){
      CH.ds[i].setAttribute('style','height:'+alF+'px;width:'+CH.an+'px;float:left;');
    }
  },
  inicio: function(){
    var div = document.createElement('div');
    div.id = CH.nID;
    var clon = CH.$(CH.idD).cloneNode(true);
    div.appendChild(clon);
    CH.$(CH.idD).parentNode.replaceChild(div,CH.$(CH.idD));
    CH.ds = CH.$(CH.idD).getElementsByTagName('li');
    CH.tD = CH.ds.length-1;
    CH.dims();
    var cntr = document.createElement('div');
    cntr.id = CH.idCn;
    (CH.$(CH.nID).nextSibling) ? (CH.$(CH.nID).parentNode).insertBefore(cntr,CH.$(CH.nID).nextSibling) : (CH.$(CH.nID).parentNode).appendChild(cntr); 
    CH.$(CH.idCn).innerHTML += '<a href="javascript:CH.desp(1)" id="ant">Anterior</a><a href="javascript:CH.desp(-1)" id="sig">Siguiente</a>';
    var ct = document.createElement('ul');
    ct.id = CH.idC;
    (CH.$(CH.nID).nextSibling) ? (CH.$(CH.nID).parentNode).insertBefore(ct,CH.$(CH.nID).nextSibling) : (CH.$(CH.nID).parentNode).appendChild(ct);
    for(var i=0;i<=CH.tD;i++){
      CH.$(CH.idC).innerHTML += '<li>'+(i+1)+'</li>';
    }
    CH.ac(CH.clC);
  }
}
 

El script pesa 2,62Kb, y 2,19 minimizado.

Un detalle pendiente…

Como hemos dicho, al programar el código hemos intentado que cumpla su función para un diseño fluido. Así es, pero queda pendiente un pequeño detalle: que el script vuelva a recalcular y asignar las dimensiones del visor y sus contenidos cuando el usuario redimensione la ventana. El obstáculo con el que nos encontramos es que un popular navegador presenta un bug serio en el evento onresize de la ventana. ¿Internet Explorer, acaso? No: Firefox. Así que si los chicos de Mozilla lo solucionan o se nos ocurre alguna solución alternativa, retocaremos la programacion.

Esta entrada se publicó el 5 de junio de 2011, se archivó en , y fue etiquetada como , . Autor: Saúl González Fernández. Aún no hay comentarios ›.

Comentarios

Aún no hay comentarios

¿Algún comentario?

* Los campos con un asterisco son necesarios

Últimos proyectos

© Digital Icon, S.L., 2007 – 2017