Cómo crear una galería web de desplazamiento infinito
Spanish (Español) translation by Andrijana Mitevska (you can also view the original English article)
Al trabajar en una galería web, me resulta molesto tener que cambiar de página; así que en el tutorial de hoy, aprenderemos cómo crear una galería de desplazamiento infinito de una página, autogenerada, con PHP y AJAX. ¡Empecemos!
Paso 1: esquema del proyecto
Comenzaremos con una página de galería normal que tiene un contenedor para nuestras imágenes, y monitorearemos la posición de desplazamiento llamando a una función de JavaScript en un intervalo rápido. Cada vez que la barra de desplazamiento está cerca de la parte inferior, haremos una solicitud AJAX a un archivo PHP externo, que devuelve una lista de nombres de imágenes. Ahora, todo lo que tendremos que hacer es agregar estas imágenes a nuestro contenedor, modificando así la altura de la página y moviendo la posición de desplazamiento hacia arriba.

Paso 2: marcado HTML
Trabajaremos con una configuración muy básica: un encabezado y el contenedor para nuestras imágenes. Las miniaturas se agruparán en conjuntos de tres filas, cada una contendrá un enlace, haciendo referencia a la imagen de tamaño completo. Después de cada grupo, agregaremos un texto que muestre el número total de imágenes mostradas y un enlace a la parte superior de la página.
1 |
<body>
|
2 |
<div id="header">Web Gallery | Infinite Scroll</div> |
3 |
<div id="container"> |
4 |
<a href="img/Achievements.jpg"><img src="thumb/Achievements.jpg" /></a> |
5 |
<a href="img/Bw.jpg"><img src="thumb/Bw.jpg" /></a> |
6 |
<a href="img/Camera.jpg"><img src="thumb/Camera.jpg" /></a> |
7 |
<a href="img/Cat-Dog.jpg"><img src="thumb/Cat-Dog.jpg" /></a> |
8 |
<a href="img/CREATIV.jpg"><img src="thumb/CREATIV.jpg" /></a> |
9 |
<a href="img/creativ2.jpg"><img src="thumb/creativ2.jpg" /></a> |
10 |
<a href="img/Earth.jpg"><img src="thumb/Earth.jpg" /></a> |
11 |
<a href="img/Endless.jpg"><img src="thumb/Endless.jpg" /></a> |
12 |
<a href="img/EndlesSlights.jpg"><img src="thumb/EndlesSlights.jpg" /></a> |
13 |
|
14 |
<p>9 Images Displayed | <a href="#header">top</a></p> |
15 |
<hr /> |
16 |
</div>
|
17 |
</body>
|

Paso 3: CSS
El CSS también es bastante básico. Primero, definimos los colores de la página y el posicionamiento del encabezado y los párrafos.
1 |
body{ |
2 |
background:#222; |
3 |
color:#666; |
4 |
}
|
5 |
#header{ |
6 |
font-family:Arial, Helvetica, sans-serif; |
7 |
font-size:24px; |
8 |
font-weight:bold; |
9 |
text-align:left; |
10 |
text-indent:35px; |
11 |
margin: 0 auto; |
12 |
width:800px; |
13 |
margin-bottom:10px; |
14 |
}
|
15 |
hr{ |
16 |
margin: 20px; |
17 |
border:none; |
18 |
border-top: 1px solid #111; |
19 |
border-bottom: 1px solid #333; |
20 |
}
|
21 |
p{ |
22 |
color:#444; |
23 |
text-align:left; |
24 |
font-size:10px; |
25 |
margin-left: 20px; |
26 |
margin-bottom: -10px; |
27 |
}
|
28 |
a{ |
29 |
color:#444; |
30 |
}
|

Paso 4
Luego, para el contenedor y las imágenes, usé un poco de CSS3 para agregar esquinas redondeadas y sombras. No olvida "-moz-box-shadow" y "-moz-border-radius" para Firefox y "-webkit-box-shadow" y "-webkit-border-radius" para Chrome y Safari.

1 |
#container{ |
2 |
margin: 0 auto; |
3 |
width:800px; |
4 |
border:1px solid #333; |
5 |
-moz-border-radius: 10px; |
6 |
-webkit-border-radius: 10px; |
7 |
font-family:Verdana, Geneva, sans-serif; |
8 |
text-align:center; |
9 |
}
|
10 |
img{ |
11 |
border:10px solid #444; |
12 |
-moz-border-radius: 5px; |
13 |
-webkit-border-radius: 10px; |
14 |
margin: 15px; |
15 |
}
|
16 |
img:hover{ |
17 |
border-color:#555; |
18 |
-moz-box-shadow: 0px 0px 15px #111; |
19 |
-webkit-box-shadow: 0px 0px 15px #111; |
20 |
}
|
Paso 5: Script PHP
Esto va a ser muy breve. Necesitamos llamar al script PHP con el índice de la siguiente imagen que necesitamos como parámetro. En primer lugar, tenemos que recuperar todos los nombres de imágenes disponibles de un directorio y guardarlos en una matriz. Organice mis imágenes en dos carpetas: "thumb" e "img" que contienen las miniaturas y las imágenes reales, respectivamente. Ten en cuenta que las miniaturas deben tener exactamente el mismo nombre que tus imágenes de tamaño completo correspondientes.

1 |
<?php
|
2 |
|
3 |
$dir = "thumb"; |
4 |
if(is_dir($dir)){ |
5 |
if($dd = opendir($dir)){ |
6 |
while (($f = readdir($dd)) !== false) |
7 |
if($f != "." && $f != "..") |
8 |
$files[] = $f; |
9 |
closedir($dd); |
10 |
}
|
Definimos una variable para el directorio del que queremos obtener los nombres de las imágenes, probamos si existe y, si podemos abrirlo, leemos todos los nombres de los archivos. Al leer una carpeta completa, siempre obtendremos dos elementos adicionales que quizás no queramos: "." - representa el directorio actual y ".." - representa el directorio principal. Para compensar, tenemos que probar si el elemento leído es diferente de estos dos, luego podemos agregarlo de manera segura a nuestra matriz.
1 |
$files[] = $f; |
Como nota, al agregar un elemento a una matriz y no especificar la posición en la que se colocará, siempre empujará el elemento al final de la matriz.
Paso 6
Ahora tenemos que construir nuestro texto de respuesta. Vamos a enviar de vuelta al JavaScript una sola cadena que contiene todos los nombres de archivo necesarios separados por un punto y coma.
1 |
$n = $_GET["n"]; |
2 |
$response = ""; |
Obtenemos el parámetro URL para el índice de la siguiente imagen que necesitamos e inicializamos nuestro texto de respuesta.
1 |
|
2 |
for($i = $n; $i<$n+9; $i++) |
3 |
$response = $response.$files[$i%count($files)].';'; |
4 |
echo $response; |
5 |
}
|
6 |
?>
|
Como dije antes, las imágenes se agruparán en conjuntos de tres filas, cada una con tres imágenes, por lo que solo necesitamos nueve imágenes para devolver los nombres de archivo de un grupo. Comenzamos en el índice que obtuvimos como parámetro, $ n, y continuamos hasta $ n + 9. En cada incremento, agregamos el nombre de nuestra imagen seguido de ";" al texto de respuesta. Aquí hay una pequeña parte complicada. No tendremos un número infinito de imágenes; así que para crear el efecto de una galería "infinita" que nunca termina, cada vez que el índice de la siguiente imagen es mayor que el número total de imágenes, debemos comenzar de nuevo desde el principio. Esto se hace aplicando la función "módulo" o "%" entre el índice y el número total de imágenes.
1 |
$i%count($files) |
Como resultado, obtenemos el resto de la división entre estos dos elementos. Por ejemplo, si el índice "$ i" es "50" y el número de imágenes "recuento ($ archivos)" es "45", el resultado será "5". Además, si "$ i" es "50" y "count ($ files)" es "65", el resultado será "50". Finalmente, tenemos que devolver nuestro texto de respuesta.
Paso 7
Aquí está el script PHP completo. Simplemente coloca tu código completo dentro de un nuevo archivo .php.
1 |
<?php
|
2 |
|
3 |
$dir = "thumb"; |
4 |
if(is_dir($dir)){ |
5 |
if($dd = opendir($dir)){ |
6 |
while (($f = readdir($dd)) !== false) |
7 |
if($f != "." && $f != "..") |
8 |
$files[] = $f; |
9 |
closedir($dd); |
10 |
}
|
11 |
|
12 |
|
13 |
$n = $_GET["n"]; |
14 |
$response = ""; |
15 |
for($i = $n; $i<$n+9; $i++){ |
16 |
$response = $response.$files[$i%count($files)].';'; |
17 |
}
|
18 |
echo $response; |
19 |
}
|
20 |
?>
|
Paso 8: JavaScript
Como de costumbre, primero definimos algunas variables que necesitaremos más adelante.
1 |
var contentHeight = 800; |
2 |
var pageHeight = document.documentElement.clientHeight; |
3 |
var scrollPosition; |
4 |
var n = 10; |
5 |
var xmlhttp; |

Para determinar el clima, la barra de desplazamiento está cerca de la parte inferior de la página, necesitamos tres variables:
- "contentHeight": la altura de la galería inicial
- "pageHeight": la altura de la página visible en el navegador
- "scrollPosition": la posición de la barra de desplazamiento medida desde la parte superior
Por último, necesitamos una variable para el siguiente índice de imagen (que vamos a enviar al script PHP) y una variable para el objeto de solicitud Ajax.
Paso 9
Necesitamos definir una función que agregará las imágenes a nuestro contenedor HTML.
1 |
function putImages(){
|
2 |
if (xmlhttp.readyState==4){
|
3 |
if(xmlhttp.responseText){
|
Un objeto de solicitud pasa por diferentes estados a medida que se realiza la solicitud, cada uno de los cuales tiene un valor numérico asociado. El que nos interesa es el estado final, cuando la solicitud está completa y el valor es "4". Primero probamos si la solicitud está en este estado y luego verificamos si recibimos una respuesta.
Paso 10
Si se cumplen ambas condiciones, tenemos que tokenizar el texto de respuesta. Esto significa que tenemos que separar los nombres de los archivos en una matriz. Recuerda que en el script PHP devolvimos una sola cadena con los nombres separados por punto y coma. Aquí hay un ejemplo: Achievements.jpg; Bw.jpg; Camera.jpg; Cat-Dog.jpg; CREATIV.jpg; creativ2.jpg; Earth.jpg; Endless.jpg; EndlesSlights.jpg;
1 |
var resp = xmlhttp.responseText.replace("\r\n", "");
|
2 |
var files = resp.split(";");
|
Hay un pequeño problema que tenemos que resolver primero; el texto de respuesta puede tener al principio un carácter de nueva línea que no queremos. Esto se soluciona fácilmente con la función "reemplazar", que toma dos parámetros: "\ r \ n" - el carácter de nueva línea, y "" - cadena vacía que reemplazará todas las apariciones del primer parámetro. Ahora todo lo que tenemos que hacer es dividir la cadena por nuestro delimitador ";".
Paso 11
A continuación, tenemos que agregar las imágenes a nuestro contenedor.
1 |
var j = 0; |
2 |
for(i=0; i<files.length; i++){
|
3 |
if(files[i] != ""){
|
4 |
document.getElementById("container").innerHTML += '<a href="img/'+files[i]+'"><img src="thumb/'+files[i]+'" /></a>';
|
5 |
j++; |
6 |
|
7 |
if(j == 3 || j == 6) |
8 |
document.getElementById("container").innerHTML += '';
|
9 |
else if(j == 9){
|
10 |
document.getElementById("container").innerHTML += '<p>'+(n-1)+" Images Displayed | <a href='#header'>top</a></p><hr />";
|
11 |
j = 0; |
12 |
} |
13 |
} |
14 |
} |
Para cada elemento de nuestra matriz, verificamos si no es una cadena vacía y agregamos la miniatura con el enlace. Tenemos que mantener un contador "j" para poder separar las imágenes en filas. Después de cada tercera y sexta miniatura agregadas, creamos una nueva línea, y después de agregar nueve miniaturas, colocamos el texto que muestra el número total de imágenes mostradas y un enlace a la parte superior de la página.
Paso 12
Aquí está la función completa.
1 |
function putImages(){
|
2 |
if (xmlhttp.readyState==4){
|
3 |
if(xmlhttp.responseText){
|
4 |
var resp = xmlhttp.responseText.replace("\r\n", "");
|
5 |
var files = resp.split(";");
|
6 |
|
7 |
var j = 0; |
8 |
for(i=0; i<files.length; i++){
|
9 |
if(files[i] != ""){
|
10 |
document.getElementById("container").innerHTML += '<a href="img/'+files[i]+'"><img src="thumb/'+files[i]+'" /></a>';
|
11 |
|
12 |
j++; |
13 |
if(j == 3 || j == 6) |
14 |
document.getElementById("container").innerHTML += '';
|
15 |
else if(j == 9){
|
16 |
document.getElementById("container").innerHTML += '<p>'+(n-1)+" Images Displayed | <a href='#header'>top</a></p><hr />";
|
17 |
j = 0; |
18 |
} |
19 |
} |
20 |
} |
21 |
} |
22 |
} |
23 |
} |
Paso 13
Ahora vamos a definir la función que verificará si la posición de desplazamiento se acerca al final y realiza la solicitud al servidor.
1 |
function scroll(){
|
2 |
|
3 |
if(navigator.appName == "Microsoft Internet Explorer") |
4 |
scrollPosition = document.documentElement.scrollTop; |
5 |
else |
6 |
scrollPosition = window.pageYOffset; |
Primero, tenemos que encontrar la posición de la barra de desplazamiento. Internet Explorer hace esto de manera un poco diferente, por lo que tenemos que determinar qué navegador está usando el cliente, luego simplemente almacenar el valor en la variable que definimos anteriormente.
Paso 14
1 |
if((contentHeight - pageHeight - scrollPosition) < 500){
|

Ahora verificamos si estamos a punto de llegar al final de nuestra galería, si la parte de la página visible en el navegador está por debajo de los 500 px inferiores de toda la página. Este no es un valor exacto, puedes usar uno diferente si lo encuentras adecuado. Si esta condición es cierta, podemos continuar y agregar nuevas imágenes.
Paso 15: Creación del objeto XMLHttpRequest
Estamos listos para crear el objeto XMLHttpRequest y enviarlo. Nuevamente, para Internet Explorer la definición es un poco diferente, por lo que debemos compensar esto también.
1 |
if(window.XMLHttpRequest) |
2 |
//Firefox, Opera, Safari |
3 |
xmlhttp = new XMLHttpRequest(); |
4 |
else |
5 |
if(window.ActiveXObject) |
6 |
//Internet Explorer |
7 |
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
8 |
else |
9 |
alert ("Bummer! Your browser does not support XMLHTTP!");
|
Paso 16
Antes de enviar la solicitud, tenemos que especificar el nombre del script PHP en el servidor e insertar los parámetros que queremos darle.
1 |
var url="getImages.php?n="+n; |
Esta es una variable de texto simple que representa la URL de la página.
Paso 17
Es hora de enviar la solicitud.
1 |
xmlhttp.open("GET",url,true);
|
2 |
xmlhttp.send(); |
La URL se establece llamando al método "abierto". El segundo parámetro es el importante, siendo la URL del script. Después de hacerlo, todo lo que necesitamos es enviarlo. Esto ejecutará el script PHP y pondrá en "xmlhttp.responseText" el valor de retorno del mismo.
Paso 18
El paso final es colocar el nuevo contenido en la página llamando a la función que definimos anteriormente "putImages" y preparar nuestras variables para la siguiente solicitud.

1 |
n += 9; |
2 |
contentHeight += 800; |
3 |
xmlhttp.onreadystatechange = putImages; |
4 |
} |
5 |
} |
Tenemos nueve imágenes nuevas en la galería, así que incrementamos "n" con 9, y necesitamos cambiar la altura de la página; así que incremente "contentHeight" con 800.
Paso 19
Aquí está todo el JavaScript que hemos utilizado.
1 |
<script> |
2 |
var contentHeight = 800; |
3 |
var pageHeight = document.documentElement.clientHeight; |
4 |
var scrollPosition; |
5 |
var n = 10; |
6 |
var xmlhttp; |
7 |
|
8 |
function putImages(){
|
9 |
|
10 |
if (xmlhttp.readyState==4) |
11 |
{
|
12 |
if(xmlhttp.responseText){
|
13 |
var resp = xmlhttp.responseText.replace("\r\n", "");
|
14 |
var files = resp.split(";");
|
15 |
var j = 0; |
16 |
for(i=0; i<files.length; i++){
|
17 |
if(files[i] != ""){
|
18 |
document.getElementById("container").innerHTML += '<a href="img/'+files[i]+'"><img src="thumb/'+files[i]+'" /></a>';
|
19 |
j++; |
20 |
|
21 |
if(j == 3 || j == 6) |
22 |
document.getElementById("container").innerHTML += '';
|
23 |
else if(j == 9){
|
24 |
document.getElementById("container").innerHTML += '<p>'+(n-1)+" Images Displayed | <a href='#header'>top</a></p><hr />";
|
25 |
j = 0; |
26 |
} |
27 |
} |
28 |
} |
29 |
} |
30 |
} |
31 |
} |
32 |
|
33 |
|
34 |
function scroll(){
|
35 |
|
36 |
if(navigator.appName == "Microsoft Internet Explorer") |
37 |
scrollPosition = document.documentElement.scrollTop; |
38 |
else |
39 |
scrollPosition = window.pageYOffset; |
40 |
|
41 |
if((contentHeight - pageHeight - scrollPosition) < 500){
|
42 |
|
43 |
if(window.XMLHttpRequest) |
44 |
xmlhttp = new XMLHttpRequest(); |
45 |
else |
46 |
if(window.ActiveXObject) |
47 |
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
|
48 |
else |
49 |
alert ("Bummer! Your browser does not support XMLHTTP!");
|
50 |
|
51 |
var url="getImages.php?n="+n; |
52 |
|
53 |
xmlhttp.open("GET",url,true);
|
54 |
xmlhttp.send(); |
55 |
|
56 |
n += 9; |
57 |
xmlhttp.onreadystatechange=putImages; |
58 |
contentHeight += 800; |
59 |
} |
60 |
} |
61 |
|
62 |
</script> |
Paso 20
Lo último que debemos hacer es ejecutar JavaScript en un intervalo específico.
1 |
<body onload="setInterval('scroll();', 250);"> |
Simplemente configura la propiedad "onload" de la etiqueta "body" y establece tu valor en la función "setInterval". Esto ejecutará la función de "desplazamiento" cada cuarto de segundo. Nuevamente, puedes cambiar este valor de tiempo, pero descubrí que es óptimo para lo que necesitamos.
¡Finalizado!
¡Hemos terminado! Espero que este tutorial te haya resultado útil. Deja un mensaje en la sección de comentarios a continuación, si necesitas más ayuda o consejo.



