От автора: При работе с веб-галереями меня раздражает то, что приходится переходить со страницы на страницу; так что в сегодняшнем учебнике мы изучим, как создать автоматически генерируемую одностраничную бесконечную веб-галерею с прокруткой при помощи PHP и AJAX. Давайте начнем!
скачайте исходники себе на компьютер!
Шаг 1: Эскиз проекта бесконечной галереи
Мы начнем с обычной страницы с галереей, у которой есть контейнер для изображений, и далее будем отслеживать позицию прокрутки, в течение коротких интервалов периодически вызывая функцию JavaScript. Каждый раз, когда полоса прокрутки нашей бесконечной галереи будет достигать нижней границы, мы будем делать запрос AJAX к внешнему файлу PHP, который возвращает список названий изображений. После этого, все, что нужно сделать – добавить эти изображения в контейнер, модифицируя, таким образом, высоту страницы и передвигая позицию прокрутки выше.
Шаг 2: Разметка HTML
Мы будем работать с очень стандартной разметкой: заголовок и контейнер для изображений. Уменьшенные изображения сгруппируем во множество из трех рядов, которые будут содержать ссылки на полноразмерные изображения. После каждой группы мы добавим текст, показывающий общее количество изображений, и ссылку к началу страницы.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<body> <div id="header">Web Gallery | Infinite Scroll</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> <a href="img/Cat-Dog.jpg"></a> <a href="img/CREATIV.jpg"></a> <a href="img/creativ2.jpg"></a> <a href="img/Earth.jpg"></a> <a href="img/Endless.jpg"></a> <a href="img/EndlesSlights.jpg"></a> <p>9 Images Displayed | <a href="#header">top</a></p> <hr /> </div> </body> |
Шаг 3: CSS
CSS тоже довольно стандартный. Во-первых, мы определяем цвета страницы и местоположение заголовка и абзацев.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
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; } |
Шаг 4
Далее для контейнера и изображений я использовал чуть-чуть CSS3 для добавления закругленных углов и теней. Не забывайте, «-moz-box-shadow»и «-moz-border-radius» используются в Firefox, а «-webkit-box-shadow» и «-webkit-border-radius» — в Chrome и Safari.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#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; } |
Шаг 5: Скрипт PHP
Это очень короткое действие. Нам нужно вызвать скрипт PHP индексом следующего изображения, который нам нужен в качестве параметра. Прежде всего, мы должны извлечь все доступные имена изображений из каталога и сохранить их в массив. Я систематизировал свои изображения в две папки: «thumb» и «img», которые содержат соответственно уменьшенные и полноразмерные. Обратите внимание, что уменьшенные изображения должны иметь точно такие же имена, как соответствующие им изображения.
1 2 3 4 5 6 7 8 9 10 |
<?php $dir = "thumb"; if(is_dir($dir)){ if($dd = opendir($dir)){ while (($f = readdir($dd)) !== false) if($f != "." && $f != "..") $files[] = $f; closedir($dd); } |
Здесь мы определяем переменную для каталога, из которого нам нужно получать изображения, проверяем, существует ли он и является ли доступным для чтения и считываем все имена файлов из него. При чтении полного содержимого папки, мы обязательно получим два дополнительных элемента, которые нам не нужны: «.» – это означает текущий каталог, и «..» – означает ссылку на родительский каталог. Чтобы учесть это, нам нужно проверять, отличается ли читаемый элемент от указанных двух, чтобы затем безопасно добавить его в свой массив.
1 |
$files[] = $f; |
Заметьте, что при добавлении элемента в массив, если не указывать позицию куда он будет помещен, он будет помещен в конец массива.
Шаг 6
Теперь нужно построить текст ответа. Мы отошлем обратно в JavaScript одну строку, содержащую все необходимые имена файлов, разделенные точкой с запятой.
1 2 |
$n = $_GET["n"]; $response = ""; |
Здесь мы получаем в качестве параметра в URL индекс следующего нужного нам изображения и инициализируем строку ответа.
1 2 3 4 5 |
for($i = $n; $i<$n+9; $i++) $response = $response.$files[$i%count($files)].';'; echo $response; } ?> |
Как я уже говорил, картинки будут сгруппированы в наборы из трех рядов, где каждый ряд будет содержать по три изображения, так что нам нужно всего девять изображений, чтобы вернуть все имена файлов в группе. Начинаем с индекса, полученного в качестве параметра, $n, и двигаемся до $n+9. При каждом приращении добавляем имя изображения, за которым следует «;», в текст ответа. Тут происходит небольшой фокус. У нас нет бесконечного количества изображений; так что для создания эффекта «бесконечной», никогда не заканчивающейся галереи, мы должны сбрасывать в начало текущий индекс каждый раз, когда он становиться больше общего количества изображений. Это сделано с применением функции «modulo» или «%» между индексом и общим количеством изображений.
1 |
$i%count($files) |
В результате этой операции мы получаем остаток от деления этих двух элементов. Например, если индекс «$i» равен «50», а количество изображений «count($files)» равно «45», результат будет равен «5». Таким же образом, если «$i» — «50», а «count($files)» — «65», результат будет «50». Наконец, нам необходимо отправить обратно текст ответа.
Шаг 7
Вот окончательный вариант скрипта для PHP. Просто поместите этот код в новый файл .php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?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
Как обычно, сначала мы определяем переменные, которые нам позже понадобятся.
1 2 3 4 5 |
var contentHeight = 800; var pageHeight = document.documentElement.clientHeight; var scrollPosition; var n = 10; var xmlhttp; |
Чтобы определить, находится ли полоса прокрутки вблизи низа страницы, нам нужны три переменные:
«contentHeight» – высота исходной галереи
«pageHeight» – высота видимой в браузере страницы
«scrollPosition» – позиция полосы прокрутки, отмеренная от верха
Наконец, нам нужна переменная для индекса следующей страницы (которую мы собираемся послать в PHP-скрипт) и переменная для объекта запроса Ajax.
Шаг 9
Здесь нам нужно определить функцию, которая добавит изображения в контейнер HTML.
1 2 3 |
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;
1 2 |
var resp = xmlhttp.responseText.replace("\r\n", ""); var files = resp.split(";"); |
Имеется небольшая проблемка, с которой мы должны справиться в первую очередь; текст ответа может начинаться с символа перевода строки, который нам не нужен. Это легко исправить при помощи функции «replace», которая принимает два параметра: «\r\n» – символ перевода строки и «» – пустая строка, которая должна заменить все вхождения первого параметра. Теперь все, что нужно сделать – это разбить строку по разделителю «;».
Шаг 11
Далее мы должны добавить изображения в свой контейнер.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var j = 0; for(i=0; i<files.length; i++){ if(files<em></em> != ""){ document.getElementById("container").innerHTML += '<a href="img/'+files<em></em>+'"><img src="thumb/'+files<em></em>+'" /></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
Вот функция в завершенном виде.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function putImages(){ if (xmlhttp.readyState==4){ if(xmlhttp.responseText){ var resp = xmlhttp.responseText.replace("\r\n", ""); var files = resp.split(";"); var j = 0; for(i=0; i<files.length; i++){ if(files<em></em> != ""){ document.getElementById("container").innerHTML += '<a href="img/'+files<em></em>+'"><img src="thumb/'+files<em></em>+'" /></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
Сейчас мы собираемся определить функцию, которая проверяет, приближается ли положение прокрутки к низу страницы, и делает запрос на сервер.
1 2 3 4 5 6 |
function scroll(){ if(navigator.appName == "Microsoft Internet Explorer") scrollPosition = document.documentElement.scrollTop; else scrollPosition = window.pageYOffset; |
Во-первых, нам нужно определить местоположение полосы прокрутки. Для Internet Explorer это делается немного по-другому, поэтому нам нужно проверить, каким браузером пользуется клиент, и затем просто сохранить это значение в переменной, которую мы ранее предусмотрели.
Шаг 14
1 |
if((contentHeight - pageHeight - scrollPosition) < 500){ |
Теперь проверяем, насколько далеко мы находимся от конца нашей галереи, т.е. не достигла ли видимая в браузере часть страницы расстояния в 500px от низа страницы. Это — не точная величина, и можно использовать любое другое значение, которое посчитаете подходящим. До тех пор, пока это условие верно, можно продолжать добавить новые изображения.
Шаг 15: Создание объекта XMLHttpRequest
Мы готовы создать объект XMLHttpRequest и отослать данные с помощью него. Снова повторяю, для Internet Explorer определения немного другие, так что мы также должны это учитывать.
1 2 3 4 5 6 7 8 9 |
if(window.XMLHttpRequest) //Firefox, Opera, Safari xmlhttp = new XMLHttpRequest(); else if(window.ActiveXObject) //Internet Explorer xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); else alert ("Bummer! Your browser does not support XMLHTTP!"); |
Шаг 16
Перед отправкой запроса нам нужно задать имя PHP-скрипта на сервере и добавить параметры, которые нужно ему придать.
1 |
var url="getImages.php?n="+n; |
Это – простая текстовая переменная, представляющая URL страницы.
Шаг 17
Настало время отправить запрос.
1 2 |
xmlhttp.open("GET",url,true); xmlhttp.send(); |
URL определяется вызовом метода «open». Второй параметр является единственно важным для нас, так как он обозначает URL скрипта. После этого все, что нам нужно – это отправить запрос с помощью send(). Это запустит PHP-скрипт, а результат его работы будет находиться в «xmlhttp.responseText».
Шаг 18
Последний шаг – разместить новый контент на странице, вызвав определенную ранее функцию «putImages», и подготовить переменные для следующего запроса.
1 2 3 4 5 |
n += 9; contentHeight += 800; xmlhttp.onreadystatechange = putImages; } } |
У нас в галерее девять новых изображений, таким образом, мы увеличиваем «n» на 9. Еще нам нужно изменить высоту страницы; поэтому увеличиваем «contentHeight» на 800.
Шаг 19
Вот использованный нами JavaScript целиком.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
<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("\r\n", ""); var files = resp.split(";"); var j = 0; for(i=0; i<files.length; i++){ if(files<em></em> != ""){ document.getElementById("container").innerHTML += '<a href="img/'+files<em></em>+'"><img src="thumb/'+files<em></em>+'" /></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; } } } } } } 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 ("Bummer! Your browser does not support XMLHTTP!"); var url="getImages.php?n="+n; xmlhttp.open("GET",url,true); xmlhttp.send(); n += 9; xmlhttp.onreadystatechange=putImages; contentHeight += 800; } } |
Шаг 20
Последнее, что мы должны сделать, это запускать JavaScript периодически с заданным интервалом времени.
1 |
<body onload="setInterval('scroll();', 250);"> |
Просто определите свойство «onload» тэга «body» и установите его значение на функцию «setInterval». Это будет запускать функцию «scroll» каждую четверть секунды. Кроме того, вы можете изменить это значение времени, но я обнаружил, что оно оптимально для того, что нам нужно.
Конец!
Мы закончили создание галереи с бесконечной прокруткой! Надеюсь, вы нашли этот учебник полезным. Пожалуйста, оставьте сообщение внизу в отделе комментариев, если в дальнейшем вам понадобится помощь или совет.
Автор: Alexandru Pitea
Перевод и редакция: Рог Виктор и Андрей Бернацкий. Команда webformyself.
Источник: //net.tutsplus.com
E-mail: contact@webformyself.com
Проект webformyself.com — Как создать свой сайт. Основы самостоятельного сайтостроения
P.S. Хотите опубликовать интересный тематический материал и заработать? Если ответ «Да», то жмите сюда.
Комментарии (5)