Фотогаллерея на JS
Часть 0. Преамбула.
Начиная с этого момента, я буду стараться регулрно писать статьи о прикладном JS. Я не буду рассуждать о преимуществах JS или его истории, я просто буду брать реальные задачи и рассказывать их решение. По мимо самого рассказа и кода у меня будут вставки, например:
---Совет-----------------------------------------------------------------------------
Сдесь будет даваться совет.
--------------------------------------------------------------------------------------
или
---Баранов спрашивает---------------------------------------------------------------Баранов - это некий герой-программист, который будет задавать вопросы, а я буду на них отвечать.
--------------------------------------------------------------------------------------
Пока я ещё не разобрался как правильно писать статьи и вставлть в них какие-нибудь нормальные изображения, я буду пользоваться для оформления ASCII графикой. Да и рисовать что либо не охота. Надеюсь вы меня за это простите. Ну а теперь приступим!
Часть 1. Постановка и соображения на счёт PHP и JS.
Многие наверное знают написанные на PHP галлереи, которые могут легко прокручиваться на манер плёнки фотоапарата, а также крайне просты в использовании. Сейчас у нас случай не обычный, перед нами поставили задачу написать JS галерею по образцу "Уцоза". Не знаю у кого-как, но в нашем регионе(Донецкая обл.) есть существенные проблемы с хостингом, и за более-менее нормальную цену можно договориться только на HTML/CSS/JS. Да и к тому же многим сайтом PHP не нужен. Так что задача - жизненна. Есть ещё одно преимушество: если пишешь довольно крупный сайт и на него будет заходить много людей, а сервер будет слабенький(всё это очень возможно), то при использовании для написания всех модулей языка PHP, можно положить сервер. Поэтому я считаю, что если что-то можно сделать посредством клиента, то это именно так и нужно делать. А разработка будет у нас проходить в три этапа: 1. Общее проэктирование. 2. Создание дизайна. 3. Разработка движка. Поскольку задача не очень сложна, то постановка не составит труда. Главное разобраться: какой хотел бы видеть галлерею заказчик? Увы, это практически не возможно сделать, и прийдёться на моменте разработки дизайна постоянно показывать своё ваяние заказчику и слушать от него упрёки. Эх, нелегка жизнь программиста... Потом мы должны будем написать пару функций и всё это соединить в одну конструкцию.
---Совет-----------------------------------------------------------------------------
Один из путей не тратить нервы заказчика (да и свои нервы тоже) - вооружиться карандашом и бумагой и постараться заставить передать бумаге мысленный образ будущей галереи. Только с ним(заказчиком) нужно вести себя крайне деликатно. Я пошёл по этому пути и после двух разорванных листов, мы сошлись на дизайне. Жаль только не всегда проходит этот приём.
--------------------------------------------------------------------------------------
Есть несколько требований к самим функциям: 1. Их можно вызывать из любой точки сайта. 2. Они должны быть максимально универсальными для всех дизайнов.
Вроде бы мы определились с тем что мы хотим получить. И можем всерьёз задуматься над тем что для этого нужно.
Часть 2. Предсатвление данных.
Я предлагал бы все библиотеки хранить в папке jslib корневой дерриктории сайта. Тогда у нас не будет дубликатов и будет простая ссылка вида myhost.ua/jslib/gallery.js. А галереи для каждой странички хранить в отдельной папке.
---Совет-----------------------------------------------------------------------------
Храните страницы в отдельных деррикториях. Например у нас есть сайт о футболе. Тогда список футбольных турниров текущего года будет храниться в football.fbc/tourn[нынешний_год]/body.html. А страничка турнира будет храниться в football.fbc/tourn[нынешний_год]/[название_турнира]/body.html. Их фотографии в football.fbc/tourn[нынешний_год]/[название_турнира]/gallery/. Благодаря этому у нас получиться ссылка на все фото типа gallery/ И нам не нужно будет каждый раз функции указывать папку из которой будут грухиться фото. Иначе у вас будет каша и через небольшой промежуток времени, вы сами не будете знать что и где храниться. При написании сайтов чаще всего используют именно такую структуру.
--------------------------------------------------------------------------------------
Но, есть большая проблема, средствами JS невозможно вернуть список файлов дерриктории. И нужно использовать шаблон. Например: img_[номер_фотографии_от_000_до_999]. Благо есть мощнейшие программы для сортировки галерей, которые позволяют это легко сделать, да и к тому же, когда фотограф сделал снимок, он его не сжимает, а отдаёт вам с весом около 2 мегобайт, а при сжатии фотографии(надеюсь, все согласяться, что сжимать фотографии нужно) можно потратить 2 секунды и написать правильное имя файла. Определясь, каким образом мы будем хранить данные мы можем приступить к созданию интерфейса.
Часть 3. Дизайн.
Для начала инициализируем библиотеку и запустим функцию построения массива(о ней, будет написано в четвёртой части)
<script type="text/javascript" src="football.fbc/jslib/gallery.js">
</script>
<body onload="gallery(24)">
</body>
Функция gallery(x) строит массив изображений по пути относительно документа из которого она запускаеться: gallery/ х - это кол-во фотографий в дерриктории.(вы можете использовать лубые другие имена, так же вы можете использовать другой дизайн, индетификаторы объектов и т.д.)
Теперь строим таблицу с тремя фотографиями:
<table align="center">
<tr><td><img src="" name="left" height="190" width="260" onClick="backImg()"></td><td><img src="" name="main"></td><td><img src="" name="right" height="190" width="260" onClick="nextImg()"></td></tr>
</table>
Я советую брать одновременно только три фотографии, хотя можно и 5, и 7, но тогда будет уменьшаться скорость загрузки, да и места на странице будет заниматься уйма. src мы оставляем пустым, поскольку не знаем что будет туда загружаться, а о функциях, я опять-таки не распространяюсь, сейчас мы строим интерфейс, а не разбираем JS библиотеку. Следующий этап - построение навигационного меню, для того что бы можно было переходить к следующе и предыдущей фотографии, а также к началу и концу(я считаю что можно оставить только возврат к началу, ибо конец это начало с перемоткой на одну фотографию).
<p align="center">
<a onClick="begin()"><img src="../../img/button/p_gal3.gif" onMouseOver="mimg=this.src; this.src='../../img/button/a_gal3.gif';" onMouseOut="this.src=mimg;"></a>
<a onClick="backImg()"><img src="../../img/button/p_gal1.gif" onMouseOver="mimg=this.src; this.src='../../img/button/a_gal1.gif';" onMouseOut="this.src=mimg;"></a>
<a onClick="nextImg()"><img src="../../img/button/p_gal2.gif" onMouseOver="mimg=this.src; this.src='../../img/button/a_gal2.gif';" onMouseOut="this.src=mimg;"></a>
<a onClick="end()"><img src="../../img/button/p_gal4.gif" onMouseOver="mimg=this.src; this.src='../../img/button/a_gal4.gif';" onMouseOut="this.src=mimg;"></a></p>
Хочу заметить приём работы с изменяемыми кнопками: когда мы наводим на них, ссылка на изображение сохраняеться в переменной и подставляеться другая ссылка, когда мы убираем курсор src присваиваеться переменная. Только надо быть осторожным, и не забывать писать this.src, а не src. Перед меню можно добавить строку статуса(т.е. общее кол-во фотографий и номер текущей фотографии):
<form>
<p align="center">
<input type="text" value=" " id="data" size="30" readonly />
</p>
</form>
Советую присвоить readonly что бы пользователь случайно не ткнул на поле. Естественно все фрагменты надо умещать до
Теперь когда мы разобрались с дизайном можно приступить к моей любимой части - написанию скрипта.
Часть 4. Написание скрипта.
Для начала нам нужна функция, которая бы заполняла массив фотографиями
var imgArray = new Array() //Создаём пустой массив
function gallery(i) { //Функция заполнения массива данными
var a = 0
while (a <= i) {
if ( a < 10) { //Если номер фотографии < 10
imgArray[a - 1] = new Image()
imgArray[a - 1].src = "gallery/img_0" + a + ".jpg"//Путь к фото
} else {
imgArray[a - 1] = new Image()
imgArray[a - 1].src = "gallery/img_" + a + ".jpg"
}
a += 1
}
begin()// Функция начального отображения
}
Большинство программ для работы с галереями, при сортировки изображений используют в именнах занчащие нули т.е. 001, а не 1. Поэтому и идёт проверка на разную степень десятки.(если нужно работать с трёхзначными номерами фотографий, то нужно изменить скрипт так что бы он приобрёл следующий вид:
var imgArray = new Array() //Создаём пустой массив
function gallery(i) { //Функция заполнения массива данными
var a = 0
while (a <= i) {
if ( a < 10) { //Если номер фотографии < 10
imgArray[a - 1] = new Image()
imgArray[a - 1].src = "gallery/img_00" + a + ".jpg"
} else if ( a < 100) { //Есди номер фотографии от 10 до 100
imgArray[a - 1] = new Image()
imgArray[a - 1].src = "gallery/img_0" + a + ".jpg"
} else {
imgArray[a - 1] = new Image()
imgArray[a - 1].src = "gallery/img_" + a + ".jpg"
}
a += 1
}
begin()// Функция начального отображения
}
ну и так далее, для работы с более крупной степенью) Данную функцию можно сделать так, что бы она работала не зависимо от кол-ва фотографий(но при условии того, что если какого-то номера не будет, то последующие номера не будут отрабатываться). Просто надо добавить блок проверки на существующие изображение:
document.main.src = "gallery/img_" + a + ".jpg"
if (document.main.height != 0) {//Если изображение существует - загружаем
imgArray[a - 1] = new Image()
imgArray[a - 1].src = "gallery/img_" + a + ".jpg"
} else {//Если нет - то считаем, что изображений больше нет
break;
}
Но скорость работы приемлема только на локальном компьютере в котором есть фотографии. Иначе загрузка страницы может затянуться на пол-минуты, взависимости от кол-ва изображений, поэтому делать это не советую, хотя и можно, да и практика показало что это не так уж и страшно.(но на некоторых серверах возможны проблемы)
---Баранов спрашивает---------------------------------------------------------------Если мы можем проверить существует данная фотография или нет, то почему мы не можем сразу работать с файлами, которые, допустим, были сняты на фотоапарате от Canon?(имя файла там следующее: DSC_[некое_большое_число]
Ответ: файла там не упорядоченны, первая фотография может называться - DSC_0909738, а вторая - DSC_8709078. Т.е. нужно перебирать все цифры, что занимает очень много времени, а главное может выдавать самые необычныерезультаты, к примеру там где лежат эти две фотографии, скрипт найдёт тысяч 5, и будет прокручивать одну и ту же фотографию.
--------------------------------------------------------------------------------------
Далее мы создадим функции управления. Только перед этим нужно усвоить, что первая строка массива это 0, а последняя array.length - 1.
function begin() {//Начальная позиция
document.main.src = imgArray[0].src//Первая фотография
document.left.src = imgArray[imgArray.length - 1].src//Последняя
document.right.src = imgArray[1].src
createData()//Возвращаем строку статуса
}
function end() {//Конечная позиция
document.main.src = imgArray[imgArray.length - 1].src//Последняя
document.left.src = imgArray[imgArray.length - 2].src
document.right.src = imgArray[0].src//Первая фотография
createData()
}
function backImg () {//Перемотка с лева на право в один шаг
var mainImg = document.main.src//Сохраняем позицию основного фото
var leftImg = document.left.src//Сохраняем позицию левого фото
for (var i = 0; i < imgArray.length; i++) {//Ищем основное фото в массиве
if (mainImg == imgArray[i].src) {
if (leftImg == imgArray[0].src) {/*Если левое изображение
- начало массива, то меняем его на конец массива*/
document.left.src = imgArray[imgArray.length - 1].src
} else if (leftImg == imgArray[imgArray.length - 1].src) {
/*Если левое фото конец массива, то перемещаемя на -1 от конца*/
document.left.src = imgArray[imgArray.length - 2].src
} else {/*Иначе новая позиция левого изображения всегда на -2 меньше старой позиции основного фото*/
document.left.src = imgArray[i - 2].src
}
//Меняем остальные изображения
document.main.src = leftImg
document.right.src = mainImg
mainImg = document.main.src
leftImg = document.left.src
break
}
}
createData()//Выводим новый статус
}
function nextImg() {//Перемотка с права на лево на один шаг
//Сохраняем позиции фотографий
var mainImg = document.main.src
var rightImg = document.right.src
for (var i = 0; i < imgArray.length; i++) {
if (mainImg == imgArray[i].src) {
/*Если правое фото конец массива, то присваиваем ему начало массива*/
if (rightImg == imgArray[imgArray.length - 1].src) {
document.right.src = imgArray[0].src
/*Если - начало, то начало + 1*/
} else if (rightImg == imgArray[0].src) {
document.right.src = imgArray[1].src
/*Иначе новая позиция правого изображения всегда на 2 больше, старой позиции основного*/
} else {
document.right.src = imgArray[i + 2].src
}
//Меняем остальные изображения
document.main.src = rightImg
document.left.src = mainImg
mainImg = document.main.src
rightImg = document.right.src
break
}
}
createData()//Вывводим статус
}
Ухххххх! Основную часть сделали, надеюсь тех коментраиев, которые встречаються в коде будет достаточно. Если всё же что-то непонятно, возьмите фотоплёнку и покрутите её влево и вправо, а потом напишите алгоритм на бумажке. Осталась последняя часть - статус.
function createData() {//Функция выводящая статус
var a = "Фотография №: "//Строка с шапкой
for (var i = 0; i < imgArray.length; i++) {//Ищем главное фото
if (document.main.src == imgArray[i].src) {//Если нашли то пишем№
a += i + 1
break;
alert(i)
}
}
a += "; " + "Всего: " + imgArray.length//Сколько всего?
document.getElementById("data").value = a//Выводим
}
Ну вот и всё, скрипт готов к работе.
P.S. Если вам понравилось и вы желаете почитать что-нибудь ещё в этом роде - оставляйте комментарии, с описанием того скрипта который вы бы хотели увидеть. Да прибудет с нами... JS 2.0! Несколько позже, дам ссылку на готовое.(хотя здесь всё есть, только листинг по кускам надо собрать)
|
Блин, купите себе орфографический словарь, а то это же просто читать невозможно! =(
Спс. Оч полезная статья
хочу ссылку на готовое!
было бы здорово если вы опишите скрипт галереи где много маленьких фоток,которые прокручиваются стрелками вправо - влево,а при нажатии появляется большое фото в блоке выше.
Спасибо! Ваша статья очень помогла быстро разобраться в основах js!
понятнее не бывает, рекомендую
Круто! Я ничего не понял, но буду разбираться. Жаль, что Вы не стали больше ни чего писать.
спасибо большое, полезная статейка)
Баранов спрашивает =))) :
а почему когда элементами массива назначается картинка
imgArray[a - 1].src = "/forum/gallery/img_00" + a + ".jpg"
я так понимаю из значения а вычитается 1 и выходит массив начинается с элемента "-1" т. к. начальное значение var а=0
я наверно, что то не понимаю ?
еще
после построения массива из картинок есть строка:
17 begin()// Функция начального отображения
функция должна выводить первую картинку массива.
но эта функция у меня не запускается и картинка не выводиться, хотя массив создан.
однако если добавить:
alert (a)
15 a += 1
16 }
17 begin()// Функция начального отображения
то функция begin() работает о_____О , но каждый раз выскакивает значение а
Все дело в "Опере" или в самом JS?
объясните нубу =)
Поздравляю вас Старо-Новым годом, желаю вам в новом году успехов и спасибо что вы находите время поддерживать ваш замечательный блог!
Отправить комментарий
Приветствуются комментарии:Для остальных вопросов и обсуждений есть форум.