Галерея без использования медиагалереи битрикса

Понадобилось мне как-то сделать на сайте под управлением Bitrix галерею изображений, без использования компонента медиагалереи. В этой записи я опишу способ решения данной задачи, тем кто хоть раз использовал LightBox читать нет смысла.

Задача

Имеем папку с сотней фотографий общим объёмом в 400 Мб. В крайне сжатые сроки необходимо сделать так, чтобы пользователь быстро и просто мог просмотреть все эти фотографии.

Поиск решения

Если создавать инфоблок с галереей, то в установленный срок никак не уложиться. Гораздо быстрее было бы воспользоваться давно проверенным jQuery плагином LightBox. Что я и сделал.

Обработка изображений

Для начала необходимо оптимизировать размер исходных файлов.

Имеем 400 мб фотографий по 10 мегапикселей каждая. Для отображения в режиме подробного просмотра достаточно чтобы фотография была шириной 950px. Размер файла не должен выходить за рамки 100-200 kb. Помимо этого, нужно еще создать небольшие изображения шириной в 100px и весом по 3-4 Кб для иконок в галерее.

Воспользовавшись массовым обработчиком файлов в фотошопе (или другом графическом редакторе) создаём две папки с изображениями. Одну для больших файлов (large) другую для маленьких (small).

Эти папки оптом загружаются в нужную директорию на веб сервере. Я залил их в /upload/unp2010/

Вывод галереи

Писать руками имена файлов и ссылки на них это долго и скучно. PHP может всё сделать за нас.

  1. <?php
  2. $smallPhotosDir = '/upload/unp2010/small'; //сюда вписывается директория с маленькими изображениями
  3. $smallPhotosServerDir = $DOCUMENT_ROOT.$smallPhotosDir; //$DOCUMENT_ROOT - путь к директории, в которой находится текущий сайт
  4. $smallPhotosArr = scandir($smallPhotosServerDir); //создаём массив с именами файлов
  5.  
  6. //тоже самое для больших файлов
  7. $largePhotosDir = '/upload/unp2010/large';
  8. $largePhotosServerDir = $DOCUMENT_ROOT.$largePhotosDir;
  9. $largePhotosArr = scandir($largePhotosServerDir);
  10. ?>

* This source code was highlighted with Source Code Highlighter.

Теперь у нас всё есть для вывода картинок. LightBox должен найти на странице картинки, каждая из которых является ссылкой на большой файл. Сделаем это.

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

  1. <div id="galery-box">
  2.   <?$lineCount = 0;//счетчик для строки
  3.   for($i = 0; $i != count($smallPhotosArr); $i++){
  4.     if($smallPhotosArr[$i] != "." and $smallPhotosArr[$i] != ".."){
  5.       if($lineCount == 0){
  6.         echo "<p>";
  7.       }
  8.       $lineCount++;?>
  9.       <a class="lightbox" href="<?=$largePhotosDir?>/<?=$largePhotosArr[$i]?>"><img src="<?=$smallPhotosDir?>/<?=$smallPhotosArr[$i]?>" /></a>
  10.       <?if($lineCount == 5){
  11.         echo "&#60;/p>";
  12.         $lineCount = 0;
  13.       }?>
  14.     <?}
  15.   }?>
  16. </div>

* This source code was highlighted with Source Code Highlighter.

Если ширина файлов разнится, то строки будут разной длинны. Это можно было бы обойти выведя все файлы в одном параграфе. Браузер бы сам их расставил как следует. Но в этом случае, ни в одном браузере кроме FireFox и Chrome нельзя бы было задать высоту строки. Без этого свойства все картинки приклеютcя друг к другу сверху и снизу.

Теперь нужно скачать и подключить jQuery и LightBox.

  1. <!--подключаем jQuery (не забудьте указать правильный путь)-->
  2. <script type="text/javascript" src="/jquery-1.4.2.min.js"></script>
  3.  
  4. <!--подключаем jQuery LightBox-->
  5. <script src="/about/js/jquery.lightbox-0.5.js" type="text/javascript"></script>
  6.  
  7. <!--подключаем css стили для LightBox-->
  8. <link rel="stylesheet" type="text/css" href="/jquery.lightbox-0.5.css" media="screen" />
  9.  

* This source code was highlighted with Source Code Highlighter.

Лайтбокс подключается очень просто, достаточно выбрать все ссылки с классом lightbox (в нашем случае) и вызвать функцию lightBox().

  1. <script type="text/javascript">
  2. $(function() {
  3.   $('.lightbox').lightBox();
  4. });
  5. </script>

* This source code was highlighted with Source Code Highlighter.

Осталось только привести это к более приглядному виду посредством пары строчек в css и можно пользоваться. Если изображений много, то можно добавить разбивку по страницам. Мне это не было нужно.

По сути, мы ни разу не использовали ни одну функцию Bitrix, так что такая галерея может быть быстро получена на любой странице, отдаваемой веб сервером с поддержкой PHP.

Все эти действия должны занять час в худшем случае. И то только если ваш компьютер будет медленно обрабатывать изображения =)

В итоге можно получить вот такую галерею.

19 комментариев

d0r0

scandir() создает массив всех файлов в директории, а если нужны выборочные файлы? к примеру, только .jpg. Собственно дело в том, что на сайте с битриксом в каждой папке создается скрытый файл «.section.php» , доступа к сайту по фтп нету и удалить его никак :(

Ответить

murzix

Этот файл отвечает за подменю. Он может появиться только если при создании раздела средствами битрикса добавлялся путь меню. Есть два выхода:

1. Создать папку через панель управления не создавая там меню. При таком способе создания папки этот файл 100% не появляется.

2. Если первое выполнить не получилось тогда нужно отредактировать вот эту строчку:

if($smallPhotosArr[$i] != "." and $smallPhotosArr[$i] != ".."){

Сюда можно добавить еще одно условие:

if($smallPhotosArr[$i] != "." and $smallPhotosArr[$i] != ".." and $smallPhotosArr[$i] != ".section.php"){

Ответить

d0r0

Спасибо за ответ. Но, даже создавая папку панели управления, файл создаётся всё равно. Сделал по другому, в строке
for($i = 0; $i != count($smallPhotosArr); $i++){
заменил «$i = 0» на «$i = 3» . А имена с картинками просто назвал цифрами, чтобы в массиве они шли после «.», «..», «section.php». Спасибо за галерею :)

Ответить

Морозов Максим

Это тоже вариант =) Главное, что работает.

Ответить

Romapad

Привет, Максим! Я создал файл, как ты описал в статье, только прикрутил к нему не лайтбокс, а другой скрипт. Но у меня выдает варминг:
Warning: scandir(/images) [function.scandir]: failed to open dir: No error in Z:\home\localhost\www\gallery\gallery.php on line 20

Warning: scandir() [function.scandir]: (errno 0): No error in Z:\home\localhost\www\gallery\gallery.php on line 20

Я запускаю на денвере, может в этом проблема? Пробовал разные пути прописывать, Document_root тоже не воспринимается…((

Ответить

Romapad

разобрался, не везде document_root работает, но можно и без него. Спасибо за статью

Ответить

Морозов Максим

Вместо $DOCUMENT_ROOT можно использовать глобальный значение из $_SERVER[‘DOCUMENT_ROOT’], тогда всё будет работать.

Но еще стоит учитывать что если сервер работает под windows, то нужно использовать другие разделители для папок. Вместо / будет \\ в путях к файлам.

Ответить

Romapad

а как узнать на какой ОС сервер сидит? У меня есть доступ только к админке битрикс, даже по фтп не залезть

Ответить

Морозов Максим

Можно на любой странице вывести содержимое массива $_SERVER

< ?print_r($_SERVER)?>

Там будет 2 записи [SERVER_SIGNATURE] и [SERVER_SOFTWARE], в них должно быть написано.

Ответить

Romapad

спасибо! Хороший материал, даже диалог про section.php пригодился)

Ответить

Женя

Уважаемый) Очень хорошая статья и все очень хорошо) Подскажите пожалуйста как сделать разбитие на страницы к примеру по 16 элементов на страницу? :)

Ответить

Морозов Максим

Можно воспользоваться вот этим методом — http://dev.1c-bitrix.ru/api_help/main/reference/cdbresult/initfromarray.php и инициализировать из массива файлов объект CDBResult, и дальше уже выводить постранично как с обычным инфоблоком.

Ответить

Женя

<?$lineCount = 0;//counter for line
for($i = 0; $i != count($smallPhotosArr); $i++){
if($smallPhotosArr[$i] != "." and $smallPhotosArr[$i] != ".."){
if($lineCount == 0){
echo "»;
}
$lineCount++;?>
<a class="example-image-link" href="/» data-lightbox=»example-set»><img class="example-image" src="/» />
<?if($lineCount == 4){
echo "»;
$lineCount = 0;
}?>

1, «NAME» => «Заголовок 1»);
$arr[] = array(«ID» => 2, «NAME» => «Заголовок 2»);
$arr[] = array(«ID» => 3, «NAME» => «Заголовок 3»);
$arr[] = array(«ID» => 4, «NAME» => «Заголовок 4»);

$rs = new CDBResult;
$rs->InitFromArray($arr);

$rs->NavStart(2);
if($rs->IsNavPrint())
{
echo «»; $rs->NavPrint(«Элементы»); echo «»;
}
?>
$order), «DF»);

// объединим файлы и каталоги в один массив
$arDirContent = array_merge($arDirs, $arFiles);

// создадим объект класса CDBResult
$rsDirContent = new CDBResult;

// инициализируем этот объект исходным массивом
$rsDirContent->InitFromArray($arDirContent);

// теперь на данном объекте
// мы можем использовать все методы класса CDBResult
// например, «Постраничная навигация»:
$rsDirContent->NavStart(50);
if($rsDirContent->IsNavPrint()) echo «»; $rs->NavPrint(«Файлы»); echo «»;
while ($arElement = $rsDirContent->Fetch()):
// если это каталог то
if ($arElement[«TYPE»]==»D»):
// выводим название каталога
echo $arElement[«NAME»];
else: // иначе если это файл то
// если это служебный файл то переходим к следующему элементу
if ($arElement[«NAME»]==».section.php») continue;
// иначе выводим его название
echo $arElement[«NAME»];
endif;
endwhile;
?>
Вот таким вот макаром у меня сейчас выглядит все это дело, помогите мне разобраться пожалуйста.. и еще хочу узнать как прикрутить шаблон свой навигации? и самое основное как выводить на странице указанное мною к-во элементов то…( Очень признателен буду за помощь!

Ответить

Женя

Ну в общем не могу понять я как собрать // объединим файлы и каталоги в один массив
$arDirContent = array_merge($arDirs, $arFiles); Как бы все понятно.. но) не могу сообразить что мне нужно собрать с примера галереи в шапке.. ну и вопрос о назначении шаблона для навигации открыт) Думаю многим начинающим мои вопросы встречались, и все были бы очень сильно благодарны за доработку этой чудо-галереи, и привидения её в божеский вид с навигацией :) Еще раз спасибо и надеюсь не вы не обойдете стороной мои, может и глупые, вопросы.

Ответить

Морозов Максим

Мысли следующие:

1. Этот скриптик — простейшая галерея, подходящая для одноразового использования. Это не пример хорошего кода и так лучше не делать.

2. Функционал битрикса включает модуль галереи. Возможно, будет проще настроить его, чем решать эти задачи.

3. Если хочется таки улучшить данный скрипт, то нужно в первую очередь вынести весь код в компоненты, чтобы отделить логику от представления. Вот тут подробно описано что это и зачем http://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=43&CHAPTER_ID=04565&LESSON_PATH=3913.4565

4. Чтобы можно было использовать навигацию, нужно переменные $smallPhotosArr и $largePhotosArr хранить в одном массиве поэлементно, чтобы потом можно было создать объект CDBResult, разбить его на страницы, и обходить итераторами.

Ответить

Дмитрий

Для того, чтобы работала пагинация необходимо привезти массив файлов в массив, как того требует битрикс array(«ID» => «номер файла», «NAME» => «имя файла»).

// Получаем изображения из директории
$path = $_SERVER[‘DOCUMENT_ROOT’] . ‘/upload/gallery’;
$indir = scandir($path);
// Исключаем из массива . и ..
$indir = array_diff($indir, array(‘.’, ‘..’));

// Создаем массив для битрикса
$arrFiles = array();
foreach($indir as $key => $value)
{

$arrFiles[] = array(«ID» => $key, «NAME» => $value);
}

// Создаем объект типа CDBResult для пагинации
$rs = new CDBResult;
$rs->InitFromArray($arrFiles);

// Указываем количество файлов для одной страницы пагинации
$rs->NavStart(20);

// Печатаем пагинацию
if($rs->IsNavPrint())
{
echo «»; $rs->NavPrint(«Фотографии»); echo «»;
}

// Выводим изображения на странице
while($rs->NavNext(true, «f_»))
{?>
<img src="/upload/gallery_thumb/» width=»150″ height=»100″ />
<?}

Успехов!

Ответить

Мария

отличная галерея)
единственное, что не понимаю, почему у меня какой то странный файл первым стоит?
все вставляю в битрикс. И первым в галерее стоит файл: . как его удалить?
понимаю откуда он взялся(я просто создала папку(раздел) и туда загрузила картинки. а файл индекс — удалила.)

может быть подскажете?

Ответить

Мария

файл «/upload/pole_narz/small/.section.php»

Ответить

Морозов Максим

Этот файл отвечает за название раздела в меню. Я выше в комментариях про него писал. Можно его добавить исключение в условном операторе на 4 строчке во втором блоке кода.

Ответить

Ваш отзыв

logo