1. Code
  2. Game Development

Galería Con Tamaños de Imágenes Personalizados (Plugin jQuery Extra)

Como prometí en mi artículo previo, aquí tienes el tutorial sobre la creación de una galería que no usa los tamaños de imagen estándar. Como extra aprenderás a crear un plugin básico jQuery para presentar las imágenes de mayor tamaño de las miniaturas de una forma más atractiva.
Scroll to top

Spanish (Español) translation by Eva Collados Pascual (you can also view the original English article)

Como prometí en mi artículo previo, aquí tienes el tutorial sobre la creación de una galería que no usa los tamaños de imagen estándar. Como extra aprenderás a crear un plugin básico jQuery para presentar las imágenes de mayor tamaño de las miniaturas de una forma más atractiva. 

Si no leíste mi artículo anterior sobre los tamaños de imágenes personalizados, por favor léelo de forma que te resulte más fácil comprender este tutorial.


Paso 1 Decidir los Tamaños de Imagen

Dependiendo de la maquetación de tu tema, y el sistema de retícula que use, podrás decidir entre diferentes tamaños de imagen para las miniaturas. Antes de decidir sobre cuantas imágenes quieres disponer en una fila, cual es la anchura del contenedor en el que las miniaturas serán mostradas, los márgenes, el padding, etc.

Yo voy a usar una anchura de 940 píxeles, una maquetación de dos columnas (un ratio de 8/4) como ejemplo, en donde el contenido tendrá 620 píxeles y la columna lateral 300 píxeles con un margen izquierdo de 20 píxeles. El área para el contenido y la columna lateral tendrán un padding interior de 20 píxeles. Ahora un poco de matemáticas: el contenido tiene 620px de anchura con un padding de 20px, esto nos deja 580px para las miniaturas; y mostrando 5 miniaturas por línea, teniendo cada una un margen derecho de 10px de forma que no estén pegadas una junto a otra; la quinta imagen de cada línea no tendrá un margen derecho; las miniaturas tendrán 108px de anchura y altura, y estarán recortadas.

La imagen más grande será como máximo 660px de ancho y 660px de alto, serán redimensionadas proporcionalmente sin recortar.

Puedes elegir que medida se ajusta a tu maquetación, si decides cambiar los tamaños, pueden ser fácilmente regenerados (ver la entrada anterior para saber cómo hacerlo), además no tienen porque ser cuadradas.


Paso 2 Configurar los Tamaños Personalizados

Edita el archivo functions.php de forma que se parezca a algo como esto:

1
2
add_action( 'after_setup_theme', 'setup' );
3
function setup() {
4
  // ...

5
6
	add_theme_support( 'post-thumbnails' );
7
	add_image_size( 'preview', 108, 108, true ); // thumbnail

8
	add_image_size( 'zoomed', 660, 600 ); // large

9
10
	// ...

11
}

Paso 3 Generar una Lista de Miniaturas, Excluyendo el Grupo de Imágenes tal y Como Aparece

Todavía en functions.php añade el métodogenerate_thumbnail_list:

1
2
function generate_thumbnail_list( $post_id = null ) {
3
	if ( $post_id == null ) return;
4
	$images = get_posts(
5
		array(
6
			'numberposts' => -1,
7
			'post_type' => 'attachment',
8
			'post_mime_type' => 'image/jpeg, image/jpg, image/png, image/gif',
9
			'post_parent' => $post_id,
10
			'orderby' => 'menu_order',
11
			'order' => 'ASC',
12
			'exclude' => get_post_thumbnail_id( $post_id )
13
		)
14
	);
15
	if ( count( $images ) > 0 ) {
16
		echo '<ul class="gallery">';
17
		foreach ( $images as $image ) {
18
			$src = wp_get_attachment_image_src($image->ID, 'zoomed');
19
			echo '<li><a href="' . $src[0] .'">' . wp_get_attachment_image( $image->ID, 'preview' ) . '</a></li>';
20
		}
21
		echo '</ul>';
22
		echo '<div class="clear"></div>';
23
	}
24
}

En el archivo content-single.php invoca el método generate_thumbnail_list, pasando como parámetro el ID de la entrada.

1
2
<?php the_content(); ?>
3
<h3>Images</h3>
4
<?php generate_thumbnail_list( get_the_ID() ); ?>

Lo anterior mostrará una lista sin orden, conteniendo enlaces a los archivos más grandes y a las miniaturas de las imágenes.


Paso 4 Aplicar Estilo a la Galería

Obviamente las miniaturas necesitan estilo, de ora forma sería sólo una simple lista de imágenes. Añade lo siguiente a tu actual hoja de estilo o crea una nueva y vincúlala:

1
2
.clear {
3
	clear: both;
4
}
5
.gallery {
6
	list-style-type: none;
7
	padding: 0;
8
	margin: 0;
9
}
10
.gallery li {
11
	float: left;
12
	margin: 0 10px 10px 0;
13
}
14
.gallery li:nth-child(5n) {
15
	margin-right: 0;
16
}
17
.gallery a {
18
	float: left;
19
	cursor: pointer;
20
	text-decoration: none;
21
}
22
.gallery img {
23
	float: left;
24
	border: 0;
25
}

Esto colocará las imágenes una junto a la otra, dejando algo de espacio alrededor.

En este punto, al pulsar sobre la miniatura se abrirá la imagen más grande en una página vacía. Ésta es una buena alternativa en caso de que JavaScript esté deshabilitado.


Paso 5 Abrir las Imágenes Con una Galería de Imagen jQuery

Aplicar Estilo a una Imagen de Galería Aumentada

Antes de escribir cualquier JavaScript sería deseable saber como se mostrará la imagen mayor. Aquí está lo que yo tenía pensado:

Nota: todo esto será generado por el plugin jQuery. Esto es sólo para mostrarte el proceso de creación.

Una capa transparente sobre todo el contenido, con la imagen en el centro y los controles en la esquina superior derecha. Mientras la imagen se carga se mostrará una rueda girando. En la raíz del cuerpo del documento se añadirá un div contenedor, el cual contedrá los enlaces para la navegación hacia la siguiente imagen y la anterior, un enlace para cerrar la galería, y el div contenedor alrededor de la imagen donde esta será cargada. Éste es código HTML mínimo que se usará para la galería.

1
2
<div id="zoom">
3
	<a href="#next" class="next">Next</a>
4
	<a href="#previous" class="previous">Previous</a>
5
	<div class="close"></div>
6
	<div class="content"></div>
7
</div>

Añadiendo el siguiente código se aplicará estilo a los elementos anteriores para que se vean como en la imagen de arriba (los comentarios están incluidos para explicar las partes que podrían no ser inmediatamente obvias):

1
2
#zoom {
3
	z-index: 99990; /* high index so it stays on top of all other elements */
4
	position: fixed; /* is fixed so if content is scrolled this stays in the same place */
5
	top: 0;
6
	left: 0;
7
	width: 100%;
8
	height: 100%;
9
	/* creates a transparent background, so the content under it will be visible,

10
	transparency can be adjusted */
11
	background: rgba(0, 0, 0, 0.8);
12
}
13
#zoom .content {
14
	z-index: 99991; /* higher index so the image will stay on top of the overlay */
15
	position: absolute;
16
	/* start initial positioning: will be centered horizontally and vertically */
17
	top: 50%;
18
	left: 50%;
19
	width: 200px;
20
	height: 200px;
21
	margin: -100px 0 0 -100px;
22
	/* end positioning */
23
	/* an animated spinner as background will be visible while the image is loading */
24
	background: #ffffff url('../img/spinner.gif') no-repeat 50% 50%;
25
	border: 20px solid #ececec;
26
	padding: 0;
27
}
28
#zoom img {
29
	display: block;
30
	max-width: none;
31
	background: #ececec;
32
	-moz-box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
33
	-webkit-box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
34
	box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
35
}
36
#zoom .close {
37
	z-index: 99993; /* higher index so the close will stay above the overlay and image */
38
	position: absolute;
39
	top: 0;
40
	right: 0;
41
	width: 49px;
42
	height: 49px;
43
	cursor: pointer;
44
	background: transparent url('../img/icons/close.png') no-repeat 50% 50%;
45
	opacity: 1;
46
	filter: alpha(opacity=100);
47
}
48
#zoom .previous,
49
#zoom .next {
50
	z-index: 99992; /* higher index so the close will stay above the overlay and image */
51
	position: absolute;
52
	top: 0;
53
	overflow: hidden;
54
	display: block;
55
	width: 49px;
56
	height: 49px;
57
	text-indent: 100%;
58
}
59
#zoom .previous {
60
	right: 100px;
61
	background: url('../img/icons/arrows.png') no-repeat 0 0;
62
}
63
#zoom .next {
64
	right: 50px;
65
	background: url('../img/icons/arrows.png') no-repeat 100% 0;
66
}
67
#zoom .close:hover {
68
	background-color: #da4f49; /* adds a red tint on hover */
69
}
70
#zoom .previous:hover,
71
#zoom .next:hover {
72
	background-color: #0088cc; /* adds a blue tint on hover */
73
}

La muestra de lo anterior:

Ahora Algo de JavaScript

El código HTML de arriba no será necesario, ya que se generará con JavaScript. Los eventos se incorporarán para abrir, navegar y cerrar la galería. Navegar y cerrar la galería puede hacerse desde el teclado o usando el ratón.

El JavaScript de abajo también está comentado para explicar lo que está sucediendo:

1
2
(function($) {
3
	$.zoom = function() {
4
		 // append a gallery wrapper to the document body

5
		$('body').append('<div id="zoom"></div>');
6
		var zoomedIn = false,  // a flag to know if the gallery is open or not

7
		    zoom = $('#zoom'),
8
		    zoomContent = null,
9
		    opened = null; // the opened image element

10
11
		function setup() {
12
			zoom.hide(); // hide it

13
			// add the inner elements, image wrapper, close and navigation links

14
			zoom.prepend('<div class="content"></div>');
15
			zoom.prepend('<div class="close"></div>');
16
			zoom.prepend('<a href="#previous" class="previous">Previous</a>');
17
			zoom.prepend('<a href="#next" class="next">Next</a>');
18
			
19
			zoomContent = $('#zoom .content');
20
			// attach events to the added elements

21
			$('#zoom .close').on('click', close);
22
			$('#zoom .previous').on('click', openPrevious);
23
			$('#zoom .next').on('click', openNext);
24
			
25
			// observe keyboard events for navigation and closing the gallery

26
			$(document).keydown(function(event) {
27
				if (!opened) {
28
					return;
29
				}
30
				if (event.which == 27) {
31
					$('#zoom .close').click();
32
					return;
33
				}
34
				if (event.which == 37) {
35
					$('#zoom .previous').click();
36
					return;
37
				}
38
				if (event.which == 39) {
39
					$('#zoom .next').click();
40
					return;
41
				}
42
				return;
43
			});
44
			
45
			if ($('.gallery li a').length == 1) {
46
				// add 'zoom' class for single image so the navigation links will hide

47
				$('.gallery li a')[0].addClass('zoom');
48
			}
49
			// attach click event observer to open the image

50
			$('.zoom, .gallery li a').on('click', open);
51
		}
52
		
53
		function open(event) {
54
			event.preventDefault(); // prevent opening a blank page with the image

55
			var link = $(this),
56
			    src = link.attr('href'),
57
				// create an image object with the source from the link

58
			    image = $(new Image()).attr('src', src).hide();
59
			if (!src) {
60
				return;
61
			}
62
			$('#zoom .previous, #zoom .next').show();
63
			if (link.hasClass('zoom')) {
64
				$('#zoom .previous, #zoom .next').hide();
65
			}
66
			
67
			// show the gallery with loading spinner, navigation and close buttons

68
			if (!zoomedIn) {
69
				zoomedIn = true;
70
				zoom.show();
71
			}
72
			
73
			// clean up and add image object for loading

74
			zoomContent.empty().prepend(image);
75
			// event observer for image loading, render() will be

76
			// called while image is loading

77
			image.load(render);
78
			opened = link;
79
		}
80
		
81
		function openPrevious(event) {
82
			event.preventDefault();
83
			if (opened.hasClass('zoom')) {
84
				return;
85
			}
86
			var prev = opened.parent('li').prev();
87
			if (prev.length == 0) {
88
				prev = $('.gallery li:last-child');
89
			}
90
			prev.children('a').trigger('click');
91
		}
92
		
93
		function openNext(event) {
94
			event.preventDefault();
95
			if (opened.hasClass('zoom')) {
96
				return;
97
			}
98
			var next = opened.parent('li').next();
99
			if (next.length == 0) {
100
				next = $('.gallery li:first-child');
101
			}
102
			next.children('a').trigger('click');
103
		}
104
		
105
		function render() {
106
			// if the image is not fully loaded do nothing

107
			if (!this.complete) {
108
				return;
109
			}
110
			var image = $(this);
111
			// if image has the same dimensions as the gallery

112
			// just show the image don't animate

113
			if (image.width() == zoomContent.width() && 
114
			    image.height() == zoomContent.height()) {
115
				show(image);
116
				return;
117
			}
118
			var borderWidth = parseInt(zoomContent.css('borderLeftWidth'));
119
			// resize the gallery to the image dimensions before

120
			// displaying the image

121
			zoomContent.animate({
122
				width: image.width(),
123
				height: image.height(),
124
				marginTop: -(image.height() / 2) - borderWidth,
125
				marginLeft: -(image.width() / 2) - borderWidth
126
			}, 300, function(){
127
				show(image);
128
			});
129
130
			function show(image) {
131
				image.fadeIn('fast');
132
			}
133
		}
134
		
135
		function close(event) {
136
			event.preventDefault();
137
			zoomedIn = false;
138
			zoom.hide();
139
			zoomContent.empty();
140
		}
141
		
142
		setup();
143
	};
144
})(jQuery);

Tras incluir el plugin de arriba, inicialízalo añadiendo la llamada al plugin en el método generate_thumbnail_list:

1
2
function generate_thumbnail_list( $post_id = null ) {
3
	// ...

4
	if ( count( $images ) > 0 ) {
5
		// ...

6
		echo '<script type="text/javascript">jQuery.zoom();</script>';
7
	}
8
}

Ejemplo

Un ejemplo de la vida real sobre como funciona esto y como se puede usar: Zoom jQuery Photo Gallery Plugin demo


Referencias