Все ленты — последние статьи

Создаем веб-галерею с бесконечной прокруткой. PHP и AJAX

При работе с галереями очень раздражает смена страниц. В данном уроке мы создадим автогенерирующую одностраничную галерею с бесконечной прокруткой контента с использованием PHP и AJAX.
demosourse
Шаг 1. Эскиз проекта

Мы начнем с обычной страницы галереи, которая содержит контейнер для наших изображений, и будем отслеживать позицию прокрутки с помощью вызова функции JavaScript с коротким интервалом. Каждый раз, когда полоска прокрутки будет находиться внизу страницы, мы будем делать AJAX запрос ко внешнему PHP файлу, который возвращает список имен изображений. После чего, все что нужно сделать — добавить эти изображения к нашему контейнеру, и модифицировать высоту страницы, премещая позицию прокрутки выше.
Схема работы приложения
Шаг 2. Разметка HTML

 

Здесь требуется только установить заголовок и контейнер для наших изображений. Миниатюры будут сгруппированы в наборы из трех строк. Каждая миниатюра содержит ссылку на полноразмерное изображение. После каждой группы мы добавим текст, который показывает общее количество выведенных изображений и ссылку на начало страницы.

<body>
<div id="header">Вэб галерея Бесконечная прокрутка</div>
<div id="container">
<a href="/img/Achievements.jpg"><img src="/thumb/Achievements.jpg" /></a>
<a href="/img/Bw.jpg"><img src="/thumb/Bw.jpg" /></a>
<a href="/img/Camera.jpg"><img src="/thumb/Camera.jpg" /></a><br />
<a href="/img/Cat-Dog.jpg"><img src="/thumb/Cat-Dog.jpg" /></a>
<a href="/img/CREATIV.jpg"><img src="/thumb/CREATIV.jpg" /></a>
<a href="/img/creativ2.jpg"><img src="/thumb/creativ2.jpg" /></a><br />
<a href="/img/Earth.jpg"><img src="/thumb/Earth.jpg" /></a>
<a href="/img/Endless.jpg"><img src="/thumb/Endless.jpg" /></a>
<a href="/img/EndlesSlights.jpg"><img src="/thumb/EndlesSlights.jpg" /></a>
<p>Показано 9 изображений <a href="#header">Вверх</a></p>
<br />
<hr />
</div>
</body>

HTML разметка
Шаг 3. CSS

CSS также весьма прост.

body{
background:#222;
color:#666;
}
#header{
font-family:Arial, Helvetica, sans-serif;
font-size:24px;
font-weight:bold;
text-align:left;
text-indent:35px;
margin: 0 auto;
width:800px;
margin-bottom:10px;
}
hr{
margin: 20px;
border:none;
border-top: 1px solid #111;
border-bottom: 1px solid #333;
}
p{
color:#444;
text-align:left;
font-size:10px;
margin-left: 20px;
margin-bottom: -10px;
}
a{
color:#444;
}

HTML и CSS
Шаг 4.

Теперь добавим немного CSS3 для скругления углов и вывода теней. Нужно испоьзовать -moz-box-shadow и -moz-border-radius для Firefox и -webkit-box-shadow и -webkit-border-radius для Chrome и Safari.

#container{
margin: 0 auto;
width:800px;
border:1px solid #333;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
font-family:Verdana, Geneva, sans-serif;
text-align:center;
}
img{
border:10px solid #444;
-moz-border-radius: 5px;
-webkit-border-radius: 10px;
margin: 15px;
}
img:hover{
border-color:#555;
-moz-box-shadow: 0px 0px 15px #111;
-webkit-box-shadow: 0px 0px 15px #111;
}

CSS3
Шаг 5. PHP скрипт

Он будет очень коротким. Нужно вызвать PHP скрипт с индексом следующего изображения которое нам нужно в качестве параметра. Первым делом мы должны взять все имена изображений из папки и сохранить их в массиве. Для хранения изображений организовано две папки: thumb и img, которые содержат миниатюры и полноразмерные изображения, соответстенно. Миниатюры должны иметь абсолютно точно такие же имена, как и полноразмерные изображения.
Папки для хранения изображений

<?php

$dir = "thumb";
if(is_dir($dir)){
if($dd = opendir($dir)){
while (($f = readdir($dd)) !== false)
if($f != "." && $f != "..")
$files[] = $f;
closedir($dd);
}

Мы определяем переменную для папки, из которой хотим извлекать имена изображений, проверяем существование папки, если она существует — открываем ее и читаем имена всех файлов, который находятся в ней. При чтении надо пропустить два элемента, которые не нужны для наших целей: "." — обозначает текущую директорию, и ".." — обозначает родительскую директорию. Также мы проверяем, можно ли прочитать файл и затем сохраняем имя в массиве.

$files[] = $f;

При добавлении элемента к массиву, в случае отсутствия явного указания позиции, всегда происходит добавление в конец массива.
Шаг 6

Теперь построим текст, который будет возвращаться из функции. Нам нужно вернуть в JavaScript единичную строку, которая содержит все необходимые имена файлов, разделенные точкой с запятой.

$n = $_GET["n"];
$response = "";

Мы получаем параметр URL для индекса следующего изображения и инициилизируем возвращаемый текст

for($i = $n; $i<$n+9; $i++)
$response = $response.$files[$i%count($files)].';';
echo $response;
}
?>

Как уже упоминалось, изображения группируются в наборы из трех строк, каждая их которых сожержит по три изображения. Таким образом нам надо вернуть только девять имен изображений для группы. Мы начинаем от индекса, который получили в качестве параметра, $n, и заканчиваем $n+9. На каждом шаге цикла мы добавляем имя изоображения и ";" после него в строку возвращаемого текста. Здесь есть небольшой трюк. Нам не нужно бесконечное количество номеров изображений. Чтобы создать эффект бесконечной галереи, которая никогда не кончается, каждый раз индекс следующего изображения должен быть больше общего количества изображений и мы должны начинать с начала. Это выполняется с помощью функции % (деление по модулю) идекса и общего количества изображений.

$i%count($files)

В результате мы получаем остаток от деления. Например, если индекс $i равен 50 и количество изображенийcount($files) составляет 45, результат будет 5. А если если индекс $i равен 50 и количество изображенийcount($files) составляет 65, то результат будет 50. В завершении мы возвращаем текст ответа.
Шаг 7

Здесь приведен полный текст PHP скрипта. Его нужно разместить в новом файле .php.

<?php

$dir = "thumb";
if(is_dir($dir)){
if($dd = opendir($dir)){
while (($f = readdir($dd)) !== false)
if($f != "." && $f != "..")
$files[] = $f;
closedir($dd);
}

$n = $_GET["n"];
$response = "";
for($i = $n; $i<$n+9; $i++){
$response = $response.$files[$i%count($files)].';';
}
echo $response;
}
?>

Шаг 8. JavaScript

Определим несколько переменных, которые понадобятся в дальнейшем:

var contentHeight = 800;
var pageHeight = document.documentElement.clientHeight;
var scrollPosition;
var n = 10;
var xmlhttp;

Переменные JavaScript

Для определения момента, когда полоса прокрутки будет находиться внизу страницы, нам нужно определить три переменные:

contentHeight — высота изначальной галереи
pageHeight — высота видимой страницы в браузере
scrollPosition — положение полосы прокрутки, отмеренное сверху

Также нам нужна будет переменная для хранения индекса следующего изображения (который мы передаем в PHP скрипт), и переменная для объекта запроса Ajax.
Шаг 9

Нужно определить функцию, которая будет добавлять изображения к нашему HTML контейнеру.

function putImages(){
if (xmlhttp.readyState==4){
if(xmlhttp.responseText){

Объект запроса изменяет свои состояния в ходе выполнения запроса. Каждое состояние ассоциируется с числовым значением. Нам интересно окончательное состояние , когда запрос завершен и значение равно 4. Сначала мы проверяем, находится ли запрос в нужном состоянии и затем проверяем, получили мы ответ или нет.
Шаг 10

Если оба условия выполнены, мы должны обработать возвращенный текст. Это означает, что мы должны разделить имена фалов и поместить их в массив. PHP скрипт возвращает единичную строку с именами, разделенными точкой с заптятой, напрмер: "Achievements.jpg;Bw.jpg;Camera.jpg;Cat-Dog.jpg;CREATIV.jpg;creativ2.jpg;Earth.jpg;Endless.jpg;EndlesSlights.jpg;"

var resp = xmlhttp.responseText.replace("rn", "");
var files = resp.split(";");

Нужно решить маленькую проблему. Текст ответа может содержать символ начала новой строки на первой позиции. А он нам не нужен. Задачча легко решается с помощью функции replace, которая принимает два параметра: "rn" — символ новой строки, и "" — пустую строку, которая заменяет все проявления первого параметра. Теперь остается только разделить строку по символу ";".
Шаг 11.

Теперь добавляем изображения в наш контейнер.

var j = 0;
for(i=0; i<files.length; i++){
if(files[i] != ""){
document.getElementById("container").innerHTML += '<a href="/img/'+files[i]+'"><img src="/thumb/'+files[i]+'" /></a>';
j++;

if(j == 3 j == 6)
document.getElementById("container").innerHTML += '';
else if(j == 9){
document.getElementById("container").innerHTML += '<p>'+(n-1)+" Images Displayed <a href='#header'>top</a></p><hr />";
j = 0;
}
}
}

Для каждого элемента в масиве, мы проверяем, не является ли строка пустой, и добавляем миниатюры вместе со ссылкой. Мы должны сохранять в контейнере "j", чтобы разделять изображения на строки. После третьей и шестой добавленной миниатюры мы создаем символ новой строки, а после девятой миниатюры мы добавляем текст, который содержит общее количество показаных изображений и ссылку наверх страницы.
Шаг 12.

Полный код функции:

function putImages(){
if (xmlhttp.readyState==4){
if(xmlhttp.responseText){
var resp = xmlhttp.responseText.replace("rn", "");
var files = resp.split(";");

var j = 0;
for(i=0; i<files.length; i++){
if(files[i] != ""){
document.getElementById("container").innerHTML += '<a href="/img/'+files[i]+'"><img src="/thumb/'+files[i]+'" /></a>';

j++;
if(j == 3 j == 6)
document.getElementById("container").innerHTML += '';
else if(j == 9){
document.getElementById("container").innerHTML += '<p>'+(n-1)+" Images Displayed <a href='#header'>top</a></p><hr />";
j = 0;
}
}
}
}
}
}

Шаг 13.

Теперь мы определим функцию, которая будет проверять, достигла ли полоса прокрутки низа страницы, и делать запрос серверу.

function scroll(){

if(navigator.appName == "Microsoft Internet Explorer")
scrollPosition = document.documentElement.scrollTop;
else
scrollPosition = window.pageYOffset;

Сначала,, надо определить положение полосы прокрутки. Internet Explorer делает это несколько по другому. Таким образом, нам надо определить, какой браузер использует клиент, а затем просто сохранить значение в переменной, определенной ранее.
Шаг 14.

if((contentHeight — pageHeight — scrollPosition) < 500){

Определение положения полосы прокрутки

Теперь мы проверяем, находимся ли мы у конца нашей галереи — если часть видимой страницы в браузере находится ниже на 500px нижней границы всей страницы. Это не точное значение, Вы можете использовать другие цифры, если они Вам больше подходят. Если условия выполняются, мы продолжаем программу операцией добавления изображений.
Шаг 15. Создание объкта XMLHttpRequest

Мы готовы к тому. чтобы создать объект XMLHttpRequest и отправить его. Для Internet Explorer определение несколько отличается

if(window.XMLHttpRequest)
//Firefox, Opera, Safari
xmlhttp = new XMLHttpRequest();
else
if(window.ActiveXObject)
//Internet Explorer
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
else
alert ("Извините! Ваш браузер не поддерживает XMLHTTP!");

Шаг 16.

Перед тем, как отправить запрос, нужно задать имя скрипта PHP на сервере и вставить параметр, который будет передавться ему.

var url="getImages.php?n="+n;

Это простая текстовая переменная, представляющая URL страницы.
Шаг 17

Пришло время отправить запрос

xmlhttp.open("GET",url,true);
xmlhttp.send();

URL устанавливается посредством вызова метода open. Второй параметр также важен — это URL скрипта. Затем выполняется метод send, который отправлет запрос на сервер. Там выполняется PHP скрипт и возвращаемое знаечение помещается в строку xmlhttp.responseText.
Шаг 18

Завершающим этапом является помещение нового контента на страницу, посредством вызова функции putImages и подготовка наших переменных для следующего запроса.
Размещение контента на странице

n += 9;
contentHeight += 800;
xmlhttp.onreadystatechange = putImages;
}
}

У нас есть девять новых изображений в галерее, таким образом мы увеличиваемn на 9. Также нужно изменить высоту страницы — увеличиваем contentHeight на 800.
Шаг 19.

Здесь полностью приведен используемый код JavaScript:

<script>
var contentHeight = 800;
var pageHeight = document.documentElement.clientHeight;
var scrollPosition;
var n = 10;
var xmlhttp;

function putImages(){

if (xmlhttp.readyState==4)
{
if(xmlhttp.responseText){
var resp = xmlhttp.responseText.replace("rn", "");
var files = resp.split(";");
var j = 0;
for(i=0; i<files.length; i++){
if(files[i] != ""){
document.getElementById("container").innerHTML += '<a href="/img/'+files[i]+'"><img src="/thumb/'+files[i]+'" /></a>';
j++;

if(j == 3 j == 6)
document.getElementById("container").innerHTML += '<br />';
else if(j == 9){
document.getElementById("container").innerHTML += '<p>'+(n-1)+" Images Displayed <a href='#header'>top</a></p><br /><hr />";
j = 0;
}
}
}
}
}
}


function scroll(){

if(navigator.appName == "Microsoft Internet Explorer")
scrollPosition = document.documentElement.scrollTop;
else
scrollPosition = window.pageYOffset;

if((contentHeight — pageHeight — scrollPosition) < 500){

if(window.XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
else
if(window.ActiveXObject)
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
else
alert ("Извините! Ваш браузер не поддерживает XMLHTTP!");

var url="getImages.php?n="+n;

xmlhttp.open("GET",url,true);
xmlhttp.send();

n += 9;
xmlhttp.onreadystatechange=putImages;
contentHeight += 800;
}
}

</script>

Шаг 20

Завершающим штрихом станет запуск JavaScript через определенные интервалы времени.

<body onload="setInterval('scroll();', 250);">

Просто установите свойство onload тэга body, и задайте ему значение с помощью функции setInterval. Таким образом запускается функция scroll каждую четверть секунды. Можно поменять значение, но опытным путем установлено, что этого достаточно.

Надеюсь, что урок Вам понравился!