Совсем недавно, занимаясь внутренним обновлением сайта, я заметил, что в некоторых статьях есть картинки большей ширины, чем сам блок с контентом. Конечно, визуальному восприятию это не мешало, тем более что, я заранее старался подгонять картинки так, чтобы текст на них оставался читаемым. Однако, заглядывая в будущее, я решил, что возможность увеличения изображения для детального его рассмотрения будет весьма кстати даже на моём скромном сайте. Поэтому я написал функциональный lightbox с элементами слайдера и галереи, которым и решил поделиться в этой статье.
По моей задумке код должен был решать несколько задач:
- Собственно сам эффект lightbox, когда при нажатии на картинку происходит затемнение фона, а изображение показывается по центру экрана;
- Возможность пролистывать картинок, относящихся только к статье, не затрагивая при этом другие изображения на странице;
- Kнопка закрытия лайтбокса и, само собой, возможность перелистывания картинок при помощи клавиш клавиатуры;
- Kнопка для открытия картинки на новой вкладке (для удобства скачивания или получения ссылки на картинку).
Это список относиться к функционалу скрипта, но хочется добавить пару пунктов относящийся к самой реализации:
- Во-первых, HTML lightbox будет добавляться после загрузки страницы через JavaScript;
- Во-вторых, при добавлении HTML учитывается наличие картинок: если их нет на странице – lightbox добавлен не будет, а если у нас на странице всего одно изображение, то будут отключены кнопки пролистывания;
- В-третьих, не забываем про адаптивность и кнопки на клавиатуре, на которые пользователь может нажать при просмотре.
Описание скрипта будет относительно примера, который я прикрепил к статье. Для работы нам потребуется подключить только jQuery библиотеку:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
Все картинки в примере лежат в элементе с id=content вперемежку с текстом. К ним мы не будем нечего прописывать и изменять их CSS. Все делаем через JavaScript – это гораздо удобнее, так как не требует дополнительных манипуляций со страницей.
Немного слов о структуре (непосредственно её рассмотрим при написании JavaScript): наш lightbox будет включать в себя несколько кнопок и обёртку для вывода изображения. Теперь для работы мы опишем CSS, который и будет отвечать за отображение:
#gallery{
background-color: rgba(24, 59, 95, 0.3);
overflow: auto;
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 100%;
-webkit-user-select: none;
-moz-user-select: none;
-o-user-select: none;
-ms-user-select: none;
user-select: none;
display: none;
z-index: 1000;
}
#gallery .prev{
background-color: rgba(24, 59, 95, 0.7);
position: fixed;
left: 0;
top: 0;
height: 100%;
width: 83px;
opacity: 0.7;
cursor: pointer;
z-index: 1;
}
#gallery .prev .icon{
display: block;
background: url(icons-gallery.png) no-repeat 1px center;
margin: 18px auto 0;
width: 14px;
height: 24px;
}
#gallery .prev:hover{
opacity: 1;
}
#gallery .viewer{
display: -webkit-flex;
display: -moz-flex;
display: -o-flex;
display: -ms-flex;
display: flex;
align-items: center;
height: 100%;
}
#gallery .viewer .image{
overflow: hidden;
margin: auto;
}
#gallery .viewer.next .image{
position: relative;
cursor: pointer;
}
#gallery .viewer .image img{
max-width: 100%;
}
#gallery .close{
position: fixed;
right: 27px;
top: 20px;
opacity: 0.7;
cursor: pointer;
z-index: 1;
}
#gallery .close .icon{
display: block;
background: url(icons-gallery.png) no-repeat -31px center;
width: 20px;
height: 20px;
}
#gallery .close:hover{
opacity: 1;
}
#gallery .zoom{
background-color: rgba(24, 59, 95, 0.7);
position: fixed;
bottom: 10px;
right: 27px;
height: 20px;
width: 20px;
border-radius: 2px;
padding: 10px;
opacity: 0.7;
cursor: pointer;
z-index: 1;
}
#gallery .zoom .icon{
display: block;
background: url(icons-gallery.png) no-repeat -11px 2px;
width: 22px;
height: 20px;
}
#gallery .zoom:hover{
opacity: 1;
}
Вышеописанный код говорит о том, что изначально lightbox будет спрятан, а в элементе с id=gallery находятся все кнопки управления (пролистывание, закрытия и открытия изображения на новой вкладке) и элемент, в котором будет отображаться выбранная картинка пользователем. Так же важно отметить, что как фон, так и кнопки зафиксированы на странице – это нужно для того чтобы при появлении скролла кнопки оставались на том же месте, а скролл происходил не по странице, а по картинке (это реализуется при помощи обрезки элемента body и компенсации правого отступа).
Переходим собственно к JavaScript. Его мы поместим в объект gallery, а весь функционал будет реализован через методы. Главный метод, а также точкой запуска/входа является initialize(containerTmp, containerImg):
- containerTmp – контейнер, куда будет помещаться HTML разметка lightbox;
- containerImg – контейнер, в котором находятся картинки, к которым будет применен скрипт.
Далее следует весь код gallery:
var gallery = {
IMGS: {},
GALLERY: {},
BODY: {},
CURRENT: 0,
initialize: function(containerTmp, containerImg){
this.IMGS = containerImg.find("img");
if(this.IMGS.length){
this.IMGS.css("cursor", "pointer");
containerTmp.append(
this.getTemp(this.IMGS.length)
);
this.GALLERY = $("#gallery");
this.BODY = $("body");
this.setUpListeners();
};
return false;
},
setUpListeners: function(){
this.IMGS.on("click", this.showHandler);
this.GALLERY.on("click", ".close", this.hideHandler);
this.GALLERY.on("click", ".zoom", this.zoomHandler);
this.GALLERY.on("click", ".prev", this.prevHandler);
this.GALLERY.on("click", ".next .image", this.nextHandler);
$(window).on("keydown", this.keydownHandler);
return false;
},
showHandler: function(){
gallery.BODY.css({
"overflow": "hidden",
"margin-left": "-17px"
});
gallery.GALLERY.show();
gallery.CURRENT = gallery.getImgPosition($(this));
gallery.setImg($(this));
return false;
},
hideHandler: function(){
gallery.BODY.removeAttr("style");
gallery.GALLERY.find(".image").html("");
gallery.GALLERY.hide();
return false;
},
zoomHandler: function(){
var img = gallery.GALLERY.find(".image img"),
src = img.attr("src");
if(img.length){
var tab = window.open(src, "_blank");
tab.focus();
};
return false;
},
prevHandler: function(){
var size = gallery.IMGS.size();
if(gallery.CURRENT){
gallery.CURRENT = --gallery.CURRENT;
}else{
gallery.CURRENT = --size;
};
gallery.setImg(
gallery.IMGS.eq(gallery.CURRENT)
);
return false;
},
nextHandler: function(){
var size = gallery.IMGS.size();
if(gallery.CURRENT >= size - 1){
gallery.CURRENT = 0;
}else if(gallery.CURRENT){
gallery.CURRENT = ++gallery.CURRENT;
}else{
gallery.CURRENT = 1;
};
gallery.setImg(
gallery.IMGS.eq(gallery.CURRENT)
);
return false;
},
keydownHandler: function(event){
if(gallery.GALLERY.css("display") == "block"){
switch(event.keyCode){
case 39:
gallery.nextHandler();
break;
case 37:
gallery.prevHandler();
break;
case 27:
gallery.hideHandler();
break;
case 40:
return false;
break;
case 38:
return false;
break;
};
};
return false;
},
getTemp: function(length){
var temp = "<div id='gallery'>";
if(length > 1){
temp += "<div class='prev'>";
temp += "<span class='icon'></span>";
temp += "</div>";
};
if(length > 1){
temp += "<div class='viewer next'>";
temp += "<div class='image'>";
temp += "</div>";
temp += "</div>";
}else{
temp += "<div class='viewer'>";
temp += "<div class='image'>";
temp += "</div>";
temp += "</div>";
};
temp += "<div class='close'>";
temp += "<span class='icon'></span>";
temp += "</div>";
temp += "<div class='zoom'>";
temp += "<span class='icon'></span>";
temp += "</div>";
temp += "</div>";
return temp;
},
getImgPosition: function(img){
var src = img.attr("src"),
num;
gallery.IMGS.each(function(i){
if($(this).attr("src") == src){
num = i;
return false;
};
});
if(num != undefined){
return num;
};
return false;
},
setImg: function(img){
var image = gallery.GALLERY.find(".image"),
src = img.attr("src"),
alt = img.attr("alt");
image.html("<img src='" + src + "' alt='" + alt + "' />");
return false;
}
};
Объект состоит из четырёх свойств и одиннадцати методов. Давайте рассмотрим их подробнее:
- IMGS – свойство, в котором хранятся все картинки;
- GALLERY – свойство, в котором храниться jQuery объект выборки динамически добавленного HTML лайтбокса;
- BODY – свойство, в котором храниться jQuery объект выборки элемента body;
- CURRENT – номер выбранной картинки пользователем;
- Initialize() – как выше было описано - точка входа;
- setUpListeners() – функция, в которой мы отображаем все события скрипта;
- showHandler() – обработка клика по картинке показ лайтбокса;
- hideHandler() – обработка клика для закрытия лайтбокса;
- zoomHandler() – отслеживание события клика по кнопке открытия картинки в новом окне;
- prevHandler() – левая навигация;
- nextHandler() - правая навигация (реализуется по нажатию на изображение);
- keydownHandler() – обработка клавиш на клавиатуре (стрелки вправо и влево, esc, отключение стрелок вверх и вниз);
- getTemp() – метод генерации шаблона галереи;
- getImgPosition() – получение текущей выбранной картинки;
- setImg() – установка изображения.
В конце страницы останется только запустить сам скрипт:
gallery.initialize(
$("body"),
$("#content")
);
Весь код написан таким образом, что, в дальнейшем, может быть легко модернизирован. К примеру, если потребуется добавить какой-нибудь красивый эффект смены картинок, то путем внесения изменений в метод setImg() этого легко можно будет добиться. Так же данный скрипт можно установить на различные CMS: Joomla, WordPress или другие.