Здесь представлю решение для вывода изображений, добавленных в Gallery (или другого подобного компонента) MODX, с использованием Ajax, разбивкой изображений на колонки (в итоге получим что то вроде вертикальной Masonry-раскладки). Здесь предусмотрено использование изображений разной высоты и их автоматический разброс по колонкам таким образом, что бы блок с изображениями был заполнен максимально (в этой части сильно не усложнял, если получится колонка сильно длинее соседних - нужно немного изменить порядок изображений в галерее.. буквально 1-2 картинки подвинуть). Заполняется первая строка, если картинок на вторую строку достаточно - вторая, если нет - заполняются наименьшие по высоте колонки.
Подобное может пригодиться когда нужно избежать долгой загрузки сайта, при большом количестве изображений. Это решение не для страниц галереи, а больше для обычных страниц, хотя можно и для альбомов приспособить.
Изображения будут загружаться одинаковыми частями, вызовом функции по кнопке "больше", или при загрузке страницы, прокрутке, другом событии.
Для нормальной работы (как задумано) понадобится:
- Компонент (приложение) Gallery (можно любую другую галерею, обращаться к БД за картинками будет из сниппета, нужно только запрос переделать)
- phpthumbof, или phpthumbon (или что то аналогичное), для изменения размера изображений
- Написать небольшой сниппет
- GIF-ка для анимации загрузки, например:
- Создать ресурс с вызовом этого сниппета
- Добавить функцию JS
- Добавить небольшой блок на страницу и вызвать функцию
Вот и все. Поехали!
HTML код блока для изображений
<section class="photog">
<div class="title">Фотогалерея</div>
<div class="items"></div>
<div class="text-center"><button class="btn btn-primary" onclick="getAjaxAlb();">Загрузить ещё</button></div>
</section>
Здесь интересного мало, есть блок с классом "items", именно в нем будем создавать колонки, в которые будут загружаться изображения. Так же есть кнопка, на которую повесим событие "onclick"
JS
Теперь функция getAjaxAlb, которая и будет выводить изображения. Разместить можно как в коде страницы, так и в отдельном файле, никаких переменных из CMS здесь нет.
Здесь не лишним будет рассказать о некоторых переменных, параметрах:
- start - количество изображений, которые уже есть на странице, используется при подгрузке новых изображений по кнопке. Используется в сниппете
- limit - количество изображений, загружаемых за 1 раз
- n_col - количество колонок. Разное для разных разрешений экрана.
- w - ширина изображений. Разная для разных разрешений экрана. Передается в сниппет и используется как параметр phpthumbof (-on)
- alb - ID альбома Gallery
- n_itm - количество полученных изображений (не всегда равно лимиту)
- n_itm_cur - количество изображений, еще не распределенных по колонкам (когда таких изображений становится меньше чем колонок, распределяем оставшиеся по колонкам с наименьшей высотой)
- col - текущая колонка, куда будет вставлено изображение
- hgs - массив с высотами колонок
Некоторые пояснения будут прямо в коде:
function getAjaxAlb() {
$('.photog .btn').hide().after('<img src="loading.gif" class="loading" alt="Загрузка" />');/*Скроем на время кнопку, вместо нее покажем анимацию*/
var start = $('.photog .column img').length;
var oknow = document.documentElement.clientWidth;
/*Параметры для разных разрешений экрана*/
if (oknow > 1200) {
var n_col = 4;
var w = 440;
var limit = 9;
}
if (oknow > 600 && oknow < 1201) {
var n_col = 3;
var w = 400;
var limit = 9;
}
if (oknow < 601) {
var n_col = 2;
var w = 300;
var limit = 6;
}
$.ajax({
url: '/ajaxfoto',
type: 'post',
data: {
alb: '1',
limit: limit,
start: start,
width: w
},
dataType: 'json',
beforeSend: function() {
$(this).html('loading');
},
complete: function() {
},
success: function(json) {
var n_itm = json.length;
var n_itm_cur = n_itm;
var col = 0;
var hgs = Array();
if (start == '0') {
/*Если это первая загрузка - добавим колонки и начнем подсчет их высоты*/
for (i = 0; i < n_col; i++) {
$('.photog .items').append('<div class="column"></div>');
hgs[i] = 0;
}
} else {
/*Иначе, просто посчитаем высоту колонок*/
i = 0;
$('.photog .column').each(function() {
hgs[i] = $(this).height();
i++;
});
}
$(json).each(function() {
$('.photog .column').eq(col).append('<img src="'+this['file']+'" alt="" />');
hgs[col] += this['height'];/*Для подсчета высоты колонок решил использовать такой вариант, как наиболее точный, учитывая одинаковую ширину изображений*/
/*Перейдем к следующей колонке*/
col++;
/*Изменяем количество оставшихся картинок*/
n_itm_cur--;
if (col == n_col) {
/*Если одна строка заполнена, переходим к первой*/
col = 0;
}
if (n_itm_cur < n_col) {
/*Если картинки заканчиваются, распределяем среди наименьших колонок (учитывая разную высоту изображений, так будет немного ровнее)*/
var h = hgs[col];
for(i=0;i<n_col;i++) {
if (hgs[i] < h) {
h = hgs[i];
col = i;
}
}
}
});
if (n_itm == limit) {
$('.photog .btn').show();/*Если изображений все еще достаточно - покажем кнопку*/
}
$('.photog .loading').remove();
}
});
}
Сниппет и ресурс с вызовом
Здесь для начала создадим ресурс для вызова сниппета, к которому будет обращаться скрипт. В моем случае это ресурс, который:
- Опубликован
- Скрыт из меню
- URI: ajaxfoto
- Содержимое (вызов сниппета. Вызывать придется некешированным):
- Шаблон: пустой
Теперь осталось создать сниппет с именем getGalImgsAj и вот таким содержимым:
<?php
$alb = (int)$_POST['alb'];
$limit = (int)$_POST['limit'];
$start = (int)$_POST['start'];
$width = (int)$_POST['width'];
$json = array();
$sql = "SELECT i.filename FROM modx_gallery_album_items ai LEFT JOIN modx_gallery_items i ON (i.id = ai.item) WHERE ai.album = '" . $alb . "' ORDER BY ai.rank LIMIT ".$start.", ".$limit;
$sel_imgs = $modx->query($sql);
$imgs = $sel_imgs->fetchAll(PDO::FETCH_ASSOC);
foreach ($imgs as $img) {
$file = 'assets/gallery/'.$img['filename'];
$options = 'w='.$width.'&zc=0';
$image = $modx->getOption('site_url').$modx->runSnippet('phpthumbof', array('input' => $file, 'options' => $options));
list($width, $height) = getimagesize($image);
$json[] = array(
'file' => $image,
'height' => $height
);
}
return json_encode($json);
Немного CSS
.photog .items {margin-left:-4px;margin-right: -4px;overflow-x: hidden;}
.photog .items:after {content: '';clear:both;display: block;}
.photog .column {width:25%;box-sizing:border-box;float:left;}
.photog .column img {width: 100%;border:4px solid #fff;box-sizing: border-box;}
@media all and (max-width: 1200px) {
.photog .column {width:33.3333%;}
}
@media all and (max-width: 600px) {
.photog .column {width:50%;}
}
Пример
Наведите на блок для первой загрузки (сделал первую загрузку по .hover())