Como hacer un Slideshow con jQuery

Un Slideshow es una presentación de imágenes que se van mostrando siguiendo una secuencia y el cambio de una imagen a la siguiente normalmente va acompañado de algún tipo de animación y también puede tener música.

Aquí vamos a ver como crear slideshows en unas pocas líneas de código usando solo jQuery para hacer las animaciones porque usando javaScript podemos cambiar la animación el numero de imágenes, el tamaño, etc. de una forma realmente sencilla y rápida. También se puede hacer un slideshow con CSS3 y así evitar el uso de jQuery pero sería más trabajoso por lo que descartamos esta opción para esta ocasión.

Vamos con unos ejemplos para ver como hacer un slideshow con jQuery sin tener que usar plugins ni ninguna otra cosa que un poco de HTML, una sencilla hoja de estilo y unas pocas líneas de jQuery.

Estructura del slideshow

El slideshow va a tener además de las imágenes un titulo o una descripción y además la imagen actuara como un enlace, en el ejemplo simplemente redirige a la imagen aunque lo habitual sería redirigirlo hacia alguna página de nuestra web, y si no se quiere enlazar nada o no se quiere ningún texto pues es tan sencillo como quitar lo que no se quiere y el slideshow seguirá funcionando igualmente como cabría esperar.


<div class="presentacion">
    <div class="contenedor">
        <div class="slide">
            <a href="img/imagen1.png">
                <img src="img/imagen1.png" title="Empieza el otoño..." alt="Empieza el otoño..." width="600px">
                <div class="info">Empieza el otoño...</div>
            </a>
        </div>
        <div class="slide">
            <a href="img/imagen2.png">
                <img src="img/imagen2.png" title="Una flor" alt="Una flor" width="600px">
                <div class="info">Una flor</div>
            </a>
        </div>
        <div class="slide">
            <a href="img/imagen3.png">
                <img src="img/imagen3.png" title="El pantano de Riaño" alt="El pantano de Riaño" width="600px">
                <div class="info">El pantano de Riaño</div>
            </a>
        </div>
        <div class="slide">
            <a href="img/imagen4.png">
                <img src="img/imagen4.png" title="Un atardecer" alt="Un atardecer" width="600px">
                <div class="info">Un atardecer</div>
            </a>
        </div>
        <div class="slide">
            <a href="img/imagen5.png">
                <img src="img/imagen5.png" title="" alt="Valdeón" width="600px">
                <div class="info">Valdeón</div>
            </a>
        </div>
        <div class="slide">
            <a href="img/imagen6.png">
                <img src="img/imagen6.png" title="Unas nubes raras" alt="Unas nubes raras" width="600px">
                <div class="info">Unas nubes raras</div>
            </a>
        </div>
        <div class="slide">
            <a href="img/imagen8.png">
                <img src="img/imagen7.png" title="Caldevilla de Valdeón" alt="Caldevilla de Valdeón" width="600px">
                <div class="info">Caldevilla de Valdeón</div>
            </a>
        </div>
        <div class="slide">
            <a href="img/imagen8.png">
                <img src="img/imagen8.png" title="Una docena de rebecos" alt="Una docena de rebecos" width="600px">
                <div class="info">Una docena de rebecos</div>
            </a>
        </div>
    </div>
</div>    

Aplicando estilo al Slideshow

Para este ejemplo es importante que las imágenes estén colocadas de forma absoluta para que estén unas encima de otras y al animar la imagen visible se vea la siguiente, pero como además de la imagen también tenemos un texto pues posicionamos de forma absoluta la clase que contiene todo. El texto también lo colocamos de forma absoluta (respecto a al div slide) para poder colocarlo sobre las imágenes.


.contenedor {
    width: 600px;
    height: 200px;
    position: relative;
    margin: 100px auto;
    background: #ccc;
    border: 2px solid #555;
    overflow: hidden;
    border: 2px solid #FFA800;
    border-radius: 10px;
    box-shadow: 0 0 4px #FFA800;
}

.contenedor:hover .info{
    color: #FFA800;
    box-shadow: 0 0 1px 1px #FFA800;
}
.slide{
    width: 600px;
    position: absolute;
}

img {
    width: 600px;
    height: 200px;
    position: relative;
}

.info {
    position: absolute;
    top: 160px;
    background: rgba(80, 80, 180, 0.5);
    border-bottom: 1px solid #FFA800;
    border-top: 1px solid #FFA800;
    height: 20px;
    width: 100%;
    padding: 5px 0;
    transition: color 1s;
}

a {
    color: #fff;
    text-decoration: none;
    text-align: center;
}

Un ejemplo sencillo: Slideshow vertical

Vamos a empezar por un ejemplo sencillo pero no por eso peor porque el efecto resultante esta bastante bien.

Para que las imágenes roten lo que hacemos es coger la imagen que se esta mostrando y ponerla la ultima, aunque como las imágenes están posicionadas de forma absoluta la imagen que se ve es la ultima porque esta encima del resto por lo que la ponemos la primera para que este debajo de todas.

De momento tenemos la forma de quitar la imagen que se esta mostrando para que se vea la siguiente, pero la idea es hacer algún tipo de animación para que las imágenes no aparezcan de golpe, y esto se puede solucionar con la función animate que nos permite animar una característica como la altura en este caso indicando cual queremos que sea la altura después de la animación, el tiempo que tardará en completarse (en milisegundos) y finalmente podemos definir una función que queramos que se ejecute al terminar la animación y en esta función cambiaremos la posición de la imagen, para que se haga justo cuando se termine la animación porque si no lo hiciésemos así se haría la animación a la vez que se esta cambiando la imagen porque mientras se esta ejecutando una animación se sigue ejecutando el resto del código a menos de que se lo indiquemos explícitamente.

Con lo explicado hasta el momento conseguimos que se cambie una imagen y se anime esa transición pero queremos que se cambien todas las imágenes de forma cíclica y para eso esta la función setInterval que nos permite definir una función e indicar cada cuanto tiempo queremos que se ejecute.

Una vez entendido que es lo que estamos haciendo vemos el código de la función y el ejemplo en vivo.


/**
* La imagen va desapareciendo de abajo a arriba. 
*/

function slideshow_vertical () {
    setInterval(function (){ // Se repite cada 5s
        $imagenMostrada = $(".contenedor .slide:last-child"); // Ultima imagen
                
        $imagenMostrada.animate({height: "0px"},2000,function() { // Anima la altura para ocultarla
            $imagenMostrada.prependTo(".contenedor"); // Se coloca la primera
        });

        $imagenMostrada.animate({height: "200px"},0); // Anima la altura para restaurarla
    }, 5000);
}

See the Pen Slideshow Jquery 1 by Ivan Salas (@isc7) on CodePen

Slideshow horizontal, vertical y efecto desvanecimiento

Usando la misma técnica que en el ejemplo anterior podemos hacer que las imágenes que se esta mostrando se desplace hacia arriba, abajo, a la derecha o a la izquierda por lo que podemos crear una función especifica para cada situación pero como los cambios serían mínimos voy a poner un ejemplo de una sencilla función que nos permite hacer estas animaciones además de combinaciones de ellas para conseguir movimientos en diagonal y para completarla un poco más también permitimos que se pueda animar la opacidad para poder tener el típico efecto desvanecimiento.


/**
* Funcion para hacer slideshows con desplazamientos y/o desvanecimientos.
*
* desp_hor: Desplazamiento horizontal en pixeles (validos valores positivos y negativos).
* desp_vert: Desplazamiento vertical en pixeles (validos valores positivos y negativos).
* opacidad: Opacidad minima que se quiere conseguir (entre 0 y 1). 
* tmp_animacion: Duracion de la animacion del desplazamiento y/o desvanecimiento (en milisegundos).
* tmp_imagen: Tiempo que transcurre hasta que se cambia la imagen (en milisegundos).
*/

function slideshow (desp_hor, desp_vert, opacidad, tmp_animacion, tmp_imagen) {
    setInterval(function (){
        $imagenMostrada = $(".contenedor .slide:last-child");
        $imagenMostrada.animate(
            {top: desp_hor, left: desp_vert, opacity:opacidad}, // Propiedades que se animan
            tmp_animacion, // Tiempo que dura la animacíon
            function() { // Se ejecuta cuando termina la animacion
                $imagenMostrada.prependTo(".contenedor"); // Coloca la ultima imagen en la primera posicion
            }
        );
            
        $imagenMostrada.animate({top: '0px', left: '0px', opacity:'1'},0); // Restaura a los valores por defecto 
    }, tmp_imagen);
}

Como decía la función es de la misma forma que la del primer ejemplo, pero se pueden animar la posición para hacer que la imagen se mueva en la dirección deseada y la opacidad, pudiendo usar una combinación de ellas o 1 sola si dejan los valores por defecto del resto. También se puede modificar el tiempo de la animación y el tiempo que se esta mostrando cada imagen.

Otra de las cosas típicas de los slideshows es que cuando colocas el ratón sobre la imagen se detiene el paso de las imágenes, vamos a ver como se hace:


    /**
* Funcion para hacer slideshows con desplazamientos y/o desvanecimientos.
*
* desp_hor: Desplazamiento horizontal en pixeles (validos valores positivos y negativos).
* desp_vert: Desplazamiento vertical en pixeles (validos valores positivos y negativos).
* opacidad: Opacidad minima que se quiere conseguir (entre 0 y 1). 
* tmp_animacion: Duracion de la animacion del desplazamiento y/o desvanecimiento (en milisegundos).
* tmp_imagen: Tiempo que transcurre hasta que se cambia la imagen (en milisegundos).
*/

function slideshow (desp_hor, desp_vert, opacidad, tmp_animacion, tmp_imagen) {
    var temporizador;
    function animar(){
        temporizador = setInterval(function (){
            $imagenMostrada = $(".contenedor .slide:last-child");
            $imagenMostrada.animate(
                {top: desp_hor, left: desp_vert, opacity:opacidad}, // Propiedades que se animan
                tmp_animacion, // Tiempo que dura la animacíon
                function() { // Se ejecuta cuando termina la animacion
                    $imagenMostrada.prependTo(".contenedor"); // Coloca la ultima imagen en la primera posicion
                }
            );
            
            $imagenMostrada.animate({top: '0px', left: '0px', opacity:'1'},0); // Restaura a los valores por defecto 
        }, tmp_imagen);
    }

    // Pausa el slideshow cuando se pone el cursor sobre las imagenes
    $(".slide").hover(
        function(){
            clearInterval(temporizador);
        },
        function(){
            animar();
        }
    );

    // Comienza la animación
    animar();
}

Si el ratón esta sobre la imagen el temporizador se detiene con clearInterval(), pero para eso tenemos que guardar el setInterval() en una variable, y cuando el ratón deja de estar encima continua el slideshow.

Puedes probar distintas efectos modificando los valores de llamada a la función al final de la pestaña de javaScript.

See the Pen Slideshow Jquery 2 by Ivan Salas (@isc7) on CodePen

Slideshow con desplazamiento de imagenes

Con la función anterior se puede hacer que las imágenes desaparezcan hacia cualquier dirección pero la siguiente imagen no tiene ningún efecto al aparecer porque ya esta detrás sin moverse, por eso vamos a ver otra alternativa para que a la vez que sale una imagen entre la siguiente deforma que parezca como si las imágenes formasen parte de una cinta que se esta moviendo.

Para conseguir esto la estructura html sigue igual pero hay que hacer algunos cambios en estilo.


.presentacion {
    width: 600px;
    height: 200px;
    position: relative;
    margin: 100px auto;
    background: #ccc;
    border: 2px solid #FFA800;
    border-radius: 10px;
    box-shadow: 0 0 4px #FFA800;
    overflow: hidden;
}

.contenedor {
    position: relative;
    height: 200px;
    word-spacing: -1em;
}

.contenedor:hover .info{
    color: #FFA800;
    box-shadow: 0 0 1px 1px #FFA800;
}

.vertical {
    top: -600px;
    width: 600px;
}

.horizontal {
    left: -600px;
    width: 4800px;

}

.horizontal .slide {
    display: inline-block;
}

.slide{
    width: 600px;
    height: 200px;
    position: relative;
    /*float: right; Para que se mueva a la derecha*/
}

img {
    width: 600px;
    height: 200px;
    position: relative;
}

.info {
    position: absolute;
    top: 160px;
    background: rgba(80, 80, 180, 0.5);
    border-bottom: 1px solid #FFA800;
    border-top: 1px solid #FFA800;
    height: 20px;
    width: 100%;
    padding: 5px 0;
    transition: color 1s;
    word-spacing: 0;
}

a {
    color: #fff;
    text-decoration: none;
    text-align: center;
}

Para este caso las imágenes ya no tienen que estar posicionadas de forma absoluta porque lo que necesitamos es que estén todas las imágenes unas detrás de otras y que cuando una va desapareciendo el resto vaya ocupando su lugar, y este es el comportamiento de los elementos si no se posicionan de forma absoluta.

Para que las imágenes se desplacen de forma vertical el ancho del contenedor en el que están las imágenes debe de ser igual al ancho de la imagen o por lo menos menor que el ancho de 2 imágenes para que cuando una imagen desaparezca la siguiente imagen suba para ocupar su hueco. Para que se desplacen de forma horizontal se necesita lo contrario, el contenedor debe de ser suficientemente ancho para contener todas las imágenes de forma que todas estén en fila y se desplacen hacia la izquierda al desaparecer una imagen (o a la derecha si se usa float: rigth;), además para que puedan estar las imágenes en fila hay que hacer que cambien su comportamiento por defecto (se muestran como un bloque) y hacer que puedan estar todas seguidas con usando display=inline-block.

Aparte de lo que hay que hacer para que se desplacen en vertical o en horizontal hay una cosa que normalmente no se observa porque no es habitual poner dos imágenes pegadas una a la otra, pero cuando esto sucede las imágenes no se ven completamente pegadas si no que aparece un espacio entre ellas y esto es porque cuando escribimos el código HTML lo lógico es poner el código tabulado para que sea más legible pero con esto lo que estamos haciendo es introducir espacios entre los elementos y normalmente no tiene importancia pero en este caso si porque las imágenes deben de aparecer juntas y para solucionarlo hay dos opciones o bien escribir todo el HTML del slideshow sin dejar ningún espacio o bien usar la opción más sensata y quitar esos espacios indeseados con CSS poniendo word-spacing: -1em; con lo que estamos quitando los espacios, pero como dentro de nuestra división también tenemos texto tenemos que poner en la clase correspondiente word-spacing: 0; para restaurar los espacios entre las palabras.

La función javascript es prácticamente igual a la del primer ejemplo, pero en lugar de coger el ultimo elemento y ponerle el primero hacemos lo contrario, ponemos el primer elemento como ultimo, aparte de esto le añadimos al contenedor la clase horizontal o vertical dependiendo del tipo desplazamiento que queremos para poder tener una sola hoja de estilo que pueda ser usada en ambos casos.


/**
* Las imagenes se desplazan horizontalmente
*/

function slideshow_horizontal () {
    $(".contenedor").addClass( "horizontal");
    setInterval(function (){
        $imagenMostrada = $(".contenedor .slide:first-child");
                
        $imagenMostrada.animate({width: "0px"},2000,function() {
            $imagenMostrada.appendTo(".contenedor");
        });
        $imagenMostrada.animate({width: "600px"},0);
    }, 3000);
}

/**
* Las imagenes se desplazan verticalmente
*/

function slideshow_vertical () {
    $(".contenedor").addClass( "vertical");
    setInterval(function (){
        $imagenMostrada = $(".contenedor .slide:first-child");
                
        $imagenMostrada.animate({height: "0px"},2000,function() {
            $imagenMostrada.appendTo(".contenedor");
        });
        $imagenMostrada.animate({height: "200px"},0);
    }, 3000);
}

Aquí puedes ver el ejemplo en acción y si quieres puedes quitar el overflow=hidden de la clase presentación y ver así como se van desplazando las imágenes y así veras como estamos haciendo lo mismo que en el primer ejemplo encogiendo la primera imagen ya sea el ancho el alto, pero esta imagen esta «fuera de pantalla» para que no se vea como se encoje, porque si no se vería un efecto similar al del primer ejemplo aunque no igual porque aquí la siguiente imagen esta entrando y en el primer ejemplo la siguiente imagen ya esta detrás.

See the Pen Slideshow Jquery 3 by Ivan Salas (@isc7) on CodePen

Finalmente, puedes descargarte el código completo de los ejemplos desde este enlace.

Leave a Reply