Показать Меню
falbar Lightbox от falbar

Lightbox от falbar или falbox

Lightbox от falbar

Совсем недавно, занимаясь внутренним обновлением сайта, я заметил, что в некоторых статьях есть картинки большей ширины, чем сам блок с контентом. Конечно, визуальному восприятию это не мешало, тем более что, я заранее старался подгонять картинки так, чтобы текст на них оставался читаемым. Однако, заглядывая в будущее, я решил, что возможность увеличения изображения для детального его рассмотрения будет весьма кстати даже на моём скромном сайте. Поэтому я написал функциональный lightbox с элементами слайдера и галереи, которым и решил поделиться в этой статье.

По моей задумке код должен был решать несколько задач:

  • собственно сам эффект lightbox, когда при нажатии на картинку происходит затемнение фона, а изображение показывается по центру экрана;
  • возможность пролистывать картинок, относящихся только к статье, не затрагивая при этом другие изображения на странице;
  • кнопка закрытия лайтбокса и, само собой, возможность перелистывания картинок при помощи клавиш клавиатуры;
  • кнопка для открытия картинки на новой вкладке (для удобства скачивания или получения ссылки на картинку).

Это список относиться к функционалу скрипта, но хочется добавить пару пунктов относящийся к самой реализации:

  • во-первых, 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() – установка изображения.

В конце страницы останется только запустить сам скрипт:

<script type="text/javascript">
	gallery.initialize(
		$("body"),
		$("#content")
	);
</script>

Весь код написан таким образом, что, в дальнейшем, может быть легко модернизирован. К примеру, если потребуется добавить какой-нибудь красивый эффект смены картинок, то путем внесения изменений в метод setImg() этого легко можно будет добиться. Так же данный скрипт можно установить на различные CMS: Joomla, Word Press или другие.

Подписаться на обновления

Комментариев еще не оставлено