Cartera de miniaturas en crecimiento

En este tutorial, crearemos una cartera con HTML5, jQuery y CSS3 que presenta un interesante efecto de crecimiento.

El HTML

Como de costumbre, comenzamos con un documento HTML5 en blanco y agregamos las hojas de estilo, el marcado y JavaScript necesarios.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Growing Thumbnails Portfolio with jQuery &amp; CSS3 | Tutorialzine Demo</title>

        <!-- The stylesheet -->
        <link rel="stylesheet" href="assets/css/styles.css" />

        <!-- Google Fonts -->
        <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Rochester|Bree+Serif" />

        <!--[if lt IE 9]>
          <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    </head>

    <body>

        <header>
            <h2>Welcome to</h2>
            <h1>Dan's Portfolio</h1>
        </header>

        <div id="main">

            <h3>My Latest Projects</h3>

            <a class="arrow prev">Prev</a>
            <a class="arrow next">Next</a>

            <ul id="carousel">
                <li class="visible"><a href=""><img src="assets/img/sites/s1.jpg" alt="" /></a></li>
            <!--  Place additional items here -->
            </ul>

        </div>

        <!-- JavaScript includes - jQuery and our own script.js -->
        <script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
        <script src="assets/js/script.js"></script>

    </body>
</html>

Lo importante a tener en cuenta aquí es el #carrusel lista desordenada. Este elemento contiene una colección de elementos li que representan sus trabajos recientes. La clase visible solo se agrega si se va a mostrar la miniatura. Solo se verán tres miniaturas a la vez. El atributo href del hipervínculo puede apuntar al sitio web en cuestión o a una versión más grande de la imagen si planea usar una caja de luz junto con este ejemplo.

JavaScript

Todo el código JavaScript/jQuery para este ejemplo reside en assets/js/script.js . Escribiremos una clase JavaScript llamada Navigator que gestionará el carrusel por nosotros. Esto implicará escribir métodos para escuchar los clics en las flechas, dividir el carrusel en grupos de 3 elementos y mostrarlos.

Así es como se usará la clase:

$(document).ready(function(){

    // Initialize the object on dom load
    var navigator = new Navigator({
        carousel: '#carousel',
        nextButton: '.arrow.next',
        prevButton: '.arrow.prev',
        // chunkSize:3,
        shuffle: true
    });

    navigator.init();
});

Cuando se cargue el documento, crearemos una instancia de la clase, pasando el carrusel div, las flechas y un parámetro opcional para si desea que la lista se baraje. Hay un parámetro más que puede ir aquí:chunkSize . Esta propiedad determina cuántas miniaturas se mostrarán a la vez, el valor predeterminado es 3.

El primer paso para lograr esto, es escribir el diseño de la clase:

// A Navigator "class" responsible for navigating through the carousel.
function Navigator(config) {

    this.carousel = $(config.carousel); //the carousel element
    this.nextButton = $(config.nextButton); //the next button element
    this.prevButton = $(config.prevButton); //the previous button element
    this.chunkSize = config.chunkSize || 3; //how many items to show at a time (maximum)
    this.shuffle = config.shuffle || false; //should the list be shuffled first? Default is false.

    //private variables
    this._items = $(config.carousel + ' li'); //all the items in the carousel
    this._chunks = []; //the li elements will be split into chunks.
    this._visibleChunkIndex = 0; //identifies the index from the this._chunks array that is currently being shown

    this.init = function () {

        // This will initialize the class, bind event handlers,
        // shuffle the li items, split the #carousel list into chunks

    }

    // Method for handling arrow clicks
    this.handlePrevClick = function(e) {};
    this.handleNextClick = function(e) {};

    // show the next chunk of 3 lis
    this.showNextItems = function() {};

    // show the previous chunk of 3 lis
    this.showPrevItems = function() {};

    // These methods will determine whether to
    // show or hide the arrows (marked as private)
    this._checkForBeginning = function() {};
    this._checkForEnd = function() {};

    // A helper function for splitting the li
    // items into groups of 3
    this._splitItems = function(items, chunk) {};
}

Usamos un guión bajo para indicar qué propiedades y métodos son privados. El código externo no debe usar ninguna propiedad que comience con un guión bajo.

En los fragmentos a continuación, puede ver cómo se implementan cada uno de los métodos. Primero viene init(), que configura el carrusel vinculando detectores de eventos y dividiendo el carrusel ul.

this.init = function () {

    //Shuffle the array if neccessary
    if (this.shuffle) {
        //remove visible tags
        this._items.removeClass('visible');

        //shuffle list
        this._items.sort(function() { return 0.5 - Math.random() });

        //add visible class to first "chunkSize" items
        this._items.slice(0, this.chunkSize).addClass('visible');
    }

    //split array of items into chunks
    this._chunks = this._splitItems(this._items, this.chunkSize);

    var self = this;

    //Set up the event handlers for previous and next button click
    self.nextButton.on('click', function(e) {
        self.handleNextClick(e);
    }).show();

    self.prevButton.on('click', function(e) {
        self.handlePrevClick(e);
    });

    // Showing the carousel on load
    self.carousel.addClass('active');
};

Los siguientes son los métodos para manejar los clics de flecha.

this.handlePrevClick = function (e) {

    e.preventDefault();

    //as long as there are some items before the current visible ones, show the previous ones
    if (this._chunks[this._visibleChunkIndex - 1] !== undefined) {
        this.showPrevItems();
    }
};

this.handleNextClick = function(e) {

    e.preventDefault();

    //as long as there are some items after the current visible ones, show the next ones
    if (this._chunks[this._visibleChunkIndex + 1] !== undefined) {
        this.showNextItems();
    }
};

Llaman a showPrevItems y showNextItems respetuosamente:

this.showNextItems = function() {

    //remove visible class from current visible chunk
    $(this._chunks[this._visibleChunkIndex]).removeClass('visible');

    //add visible class to the next chunk
    $(this._chunks[this._visibleChunkIndex + 1]).addClass('visible');

    //update the current visible chunk
    this._visibleChunkIndex++;

    //see if the end of the list has been reached.
    this._checkForEnd();

};

this.showPrevItems = function() {

    //remove visible class from current visible chunk
    $(this._chunks[this._visibleChunkIndex]).removeClass('visible');

    //add visible class to the previous chunk
    $(this._chunks[this._visibleChunkIndex - 1]).addClass('visible');

    //update the current visible chunk
    this._visibleChunkIndex--;

    //see if the beginning of the carousel has been reached.
    this._checkForBeginning();

};

Los métodos anteriores eliminan o asignan el visible class, que es como controlamos la visibilidad de las miniaturas. Es una buena idea ocultar la flecha anterior/siguiente si no hay más elementos para mostrar. Esto se hace con checkForBeginning y checkForEnd métodos.

this._checkForBeginning = function() {
    this.nextButton.show(); //the prev button was clicked, so the next button can show.

    if (this._chunks[this._visibleChunkIndex - 1] === undefined) {
        this.prevButton.hide();
    }
    else {
        this.prevButton.show();
    }
};

this._checkForEnd = function() {
    this.prevButton.show(); //the next button was clicked, so the previous button can show.

    if (this._chunks[this._visibleChunkIndex + 1] === undefined) {
        this.nextButton.hide();
    }
    else {
        this.nextButton.show();
    }
};

Por último, aquí están los splitItems método, que genera los fragmentos. Se basa en el método JavaScript de empalme para eliminar partes de la matriz y agregarlas a la matriz splitItems (se convierte en una matriz de matrices):

this._splitItems = function(items, chunk) {

    var splitItems = [],
    i = 0;

    while (items.length > 0) {
        splitItems[i] = items.splice(0, chunk);
        i++;
    }

    return splitItems;

};

¡Felicitaciones! Ahora tiene un ejemplo de trabajo. Solo nos queda estilizarlo.

El CSS

El estilo de la cartera se define en assets/css/styles.css. Aquí solo se muestran las partes más interesantes, ya que el resto se omite por brevedad.

#carousel{
    margin-top:200px;
    text-align:center;
    height:60px;
    background-color:#111;
    box-shadow:0 3px 5px #111;

    /* Initially hidden */
    opacity:0;

    /* Will animate the grow effect */
    -moz-transition:0.4s opacity;
    -webkit-transition:0.4s opacity;
    transition:0.4s opacity;
}

#carousel.active{
    opacity:1;
}

/* The thumbnails, hidden by default */

#carousel li{
    display:none;
    list-style:none;
    width:150px;
    height:150px;
    margin: -82px 18px 0;
    position:relative;

    -moz-transition:0.4s all;
    -webkit-transition:0.4s all;
    transition:0.4s all;
}

/* This class will show the respective thumbnail */

#carousel li.visible{
    display:inline-block;
}

#carousel li a img{
    border:none;
}

#carousel li img{
    display:block;
    width:auto;
    height:auto;
    max-width:100%;
    max-height:100%;
    position:relative;
    z-index:10;
}

/* Creating the cradle below the thumbnails.
    Uses % so that it grows with the image. */

#carousel li:after{
    content:'';
    background:url('../img/cradle.png') no-repeat top center;
    background-size:contain;
    bottom: 4%;
    content: "";
    height: 50px;
    left: -6.5%;
    position: absolute;
    right: -6.5%;
    width: auto;
    z-index: 1;
}

/* Enlarging the thumbnail */

#carousel li:hover{
    height: 197px;
    margin-top: -152px;
    width: 222px;
}

¡Con esto, nuestra cartera de miniaturas en crecimiento está completa!

¡Es una envoltura!

Puede personalizar fácilmente el ejemplo de hoy incorporando un script de caja de luz, aumentando la cantidad de miniaturas que se muestran a la vez o incluso convirtiéndolo en una galería. Si haces algo interesante, ¡asegúrate de compartirlo en la sección de comentarios a continuación!