Делаем слайд-шоу с использованием jQuery

Июнь, 29. 2011 год

Технология Flash все реже и реже используется для интерактивных элементов web-страниц. Это происходит благодаря развитию технологии CSS и появлению различных JS библиотек. Одной из таких библиотек является jQuery. Ее функционал позволяет легко получать доступ к любому элементу DOM, обращаться к атрибутам и содержимому элементов DOM, манипулировать ими. Рассмотрим использование некоторых функций jQuery на примере создания слайд-шоу.

Но прежде чем писать скрипты, давайте сначала определимся со структурой нашего слайд-шоу и опишем ее с помощью HTML.

img01 Делаем слайд шоу с использованием jQuery

Как мы видим на рисунке, наше слайдшоу представляет собой выстроенные в один ряд изображения и стрелки прокрутки. Опишем данную структуру следующим HTML кодом:

<div id="gallery">
	<div class="container">
		<ul>
			<li><img src="img/img01.jpg" /></li>
			<li><img src="img/img02.jpg" /></li>
			<li><img src="img/img03.jpg" /></li>
			<li><img src="img/img04.jpg" /></li>
		</ul>
	</div>
	<div class="nav prev"><a href="#" title="назад">назад</a></div>
	<div class="nav next"><a href="#" title="вперед">вперед</a></div>
</div>

Здесь роль стрелок навигации у нас будут выполнять ссылки «назад» и «вперед», а списком изображений будет служить список, расположенный в блоке с классом container.

Теперь перейдем к описанию CSS. Так как блок нашего слайд-шоу должен быть по ширине резиновым, присваиваем всем блокам, лежащим внутри внешнего блока gallery свойство float: left, тем самым выстраивая их в один ряд. Затем блок с изображениями делаем на всю ширину родительского блока, стрелку «назад» отодвигаем влево на величину ширины родительского блока, а стрелку «вперед» отодвигаем влево на свою ширину. Ширина стрелок навигации у нас будет равна 40 px. Для того чтобы лучше понять наши манипуляции взгляните на рисунок.

img02 Делаем слайд шоу с использованием jQuery

Теперь займемся списком с изображениями. Наша задача расположить их в ряд, но так чтобы он не переносился на другую строку, если его длина будет больше чем длина родительского блока. Для этого присвоим списку свойства white-space: nowrap и overflow: hidden. Первое запретит перенос дочерних элементов на следующую строку, а второе скроет элементы, выходящие за ширину списка. Элементам списка присвоим, в свою очередь свойства display: inline тем самым разместив их в горизонтальный ряд подобно обычному тексту.

Настала очередь заняться стилизацией стрелок навигации. Делаем их размеры такие же, как и родительский блок и скрываем текст внутри них. Открываем любой графический редактор и делаем изображения стрелок «назад» и «вперед». У меня получились вот такие:

img03 Делаем слайд шоу с использованием jQuery

После всех манипуляций у нас получается следующий код CSS:

#gallery div.container {
	width: 100%;
	float: left;
	overflow: hidden;
}
 
#gallery ul {
	overflow:hidden;
	list-style:none;
	margin:0;
	padding:0;
	white-space:nowrap;
	width:100%;
}
 
#gallery ul li {
	display:inline;
}
 
#gallery div.nav {
	float:left;
	height:150px;
	width:40px;
}
 
#gallery div.prev {
	margin-left: -100%;
}
 
#gallery div.next {
	margin-left: -40px;
}
 
#gallery div.nav a {
	display:block;
	width:100%;
	height:100%;
	overflow:hidden;
	text-indent:-1000px;
	opacity:0.5;
	filter: alpha(opacity = 50);
}
#gallery div.prev a {
	background:url(prev.png) no-repeat center center #eee;
}
 
#gallery div.next a {
	background:url(next.png) no-repeat center center #eee;
}
 
#gallery div.nav a:hover {
	opacity:0.7;
	filter: alpha(opacity = 70);
}

Обратите внимание на то, что в описании стиля ссылок есть два свойства: opacity и filter. Задача у них двоих одинаковая: задать прозрачность элементу. Второй параметр необходим корректного отображения в браузере IE, т.к. свойство opacity он не понимает.

Если вы в коде HTML делали пункты списка с изображениями делали каждый на отдельной строке, то вы могли заметить что между изображениями есть пробелы. Их наличие обусловлено тем, что элементы списка воспринимаются как строчные элементы, а переход на новую строку воспринимается как пробел. От этих пробелов можно 2-мя способами:

  • С помощью CSS-свойства word-spacing, присвоив ему отрицательную ширину пробельного символа. Недостаток этого способа состоит в том, что у каждого размера и типа шрифта эта величина разная и вам нужно будет экспериментально каждый раз подбирать ее.
  • Убрать лишние символы между элементами списка: вручную или с помощью JS. Данный метод является более предпочтительным, тем более недостатков у него я не вижу.

Итак, структура слайд-шоу готова, осталось только заставить ее двигаться. Суть пролистывания изображений заключается в динамическом изменении CSS-свойства text-indent у списка, в котором они находятся. Задавая свойству положительное значение, мы сдвигаем дочерние элементы вправо, отрицательное значение — влево. Для того чтобы прокрутить весь список до конца его нужно сместить влево на разницу значений ширины этого списка элементов и ширины родительского элемента. Эти величины можно получить из DOM свойств объекта. Свойство scrollWidth определяет ширину списка элементов в объекте, а clientWidth — ширину самого объекта.

img04 Делаем слайд шоу с использованием jQuery

Разностью этих величин у нас будет параметр width:

var width = $("#gallery ul").attr("scrollWidth") - $("#gallery ul").attr("clientWidth");

Для динамического изменения свойства text-indent нам идеально подходит функция jQuery animate (). Она позволяет осуществлять анимацию списка CSS-свойств за заданный промежуток времени. Полное описание с примерами можно прочитать на сайте jQuery. Какое CSS-свойство изменять, мы уже определили, осталось разобраться со временем, за которое будет происходить анимация – для этого заведем переменную elapsed. Чтобы каждый раз не подбирать необходимое время для прокрутки всех изображений просто возьмем ширину списка элементов и умножим на некий коэффициент – переменная factor. Чем больше значение коэффициента – тем медленней будет осуществляться прокрутка.

var factor = 2.5;
var elapsed = width * factor;

Для того чтобы привязать анимацию к стрелкам навигации возьмем методы mouseenter или mousedown. Первый срабатывает при наведении курсора мыши на объект, второй – при нажатии кнопкой мыши на объект. Получаем следующий код:

$("#gallery .prev").mouseenter ( function () {
	$("#gallery ul").stop(true);
	indent = - parseInt ( $("#gallery ul").css("text-indent") );
	$("#gallery ul").animate({ textIndent: 0}, elapsed - ( width - indent ) * factor );
});
 
$("#gallery .next").mouseenter ( function () {
	$("#gallery ul").stop(true);
	indent = - parseInt ( $("#gallery ul").css("text-indent") );
	$("#gallery ul").animate({ textIndent: -width}, ( width - indent ) * factor );
});

Как вы могли заметить, в коде мы используем еще одну функцию jQuery — stop (). Она предназначена для остановки, происходящей в данное время анимации элемента. Ей мы передаем один параметр, который означает, что мы хотим очистить очередь анимации. Так же, у нас появляется переменная indent в которую мы записываем текущее значение СSS-свойства text-indent. Эта величина нам понадобится при расчете времени, которое потребуется на анимацию CSS-свойства при его текущем значении.

Код, запускающий анимацию, у нас уже есть, теперь нужен код, который бы ее останавливал. Для этого возьмем метод mouseleave или mouseup. Первый срабатывает, когда мы убираем курсор с объекта, второй – когда отпускаем нажатую кнопку мыши.

$("#gallery .prev").mouseleave ( function () {
	$("#gallery ul").stop(true);
});
 
$("#gallery .next").mouseleave ( function () {
	$("#gallery ul").stop(true);
});

Итак, у нас уже фактически есть работающее слайд-шоу. Почему фактически? Потому что в браузерах на основе движка Webkit оно не работает. В ходе недолгих разбирательств, мы узнаем, что это браузеры, работающие на этом движке, просчитывают параметры scrollWidth и clientWidth когда документ уже полностью загружен, в отличие от остальных, которые делают это, когда страница показывается пользователю. Поэтому добавляем следующий код:

if ($.browser.webkit &amp;&amp; document.readyState != "complete"){
	setTimeout( arguments.callee, 100 );
	return;
}

Он проверяет браузер и состояние готовности страницы. Если движок браузера Webkit и состояние готовности не является «complete», то весь JS-код запускается повторно через 100 мс.

Теперь наше слайд-шоу работает как надо во всех браузерах, но есть еще одна вещь, которой, как мне кажется, не хватает – плавность прокрутки, особенно когда при ее остановке. Давайте сделаем этот процесс более плавным. Для этого нам потребуется специальная библиотека jQuery UI. Она обеспечивает работу с анимацией, эффектами, интерфейсом и всевозможными виджетами. Для нашей задачи нужны функции характера воспроизведения анимации – easing. На странице вы можете наглядно увидеть как работает каждая функция воспроизведения и выбрать подходящую. Эта функция затем передается параметром функции animate. Я выбрал для примера easeOutQuad. Допишем наши функции для прекращения анимации:

$("#gallery .prev").mouseleave ( function () {
	$("#gallery ul").stop(true);
	indent = - parseInt ( $("#gallery ul").css("text-indent") );
 
	if ( indent &gt; widthStop )
		$("#gallery ul").animate({ textIndent: "+="+widthStop }, widthStop * factorStop, "easeOutQuad" );
	else if ( indent &gt; 0 )
		$("#gallery ul").animate({ textIndent: 0 }, indent * factorStop, "easeOutQuad" );
});
 
$("#gallery .next").mouseleave ( function () {
	$("#gallery ul").stop(true);
	indent = - parseInt ( $("#gallery ul").css("text-indent") );
	var delta = width - indent;
	if ( delta &gt; widthStop )
		$("#gallery ul").animate({ textIndent: "-="+widthStop }, widthStop * factorStop, "easeOutQuad");
	else if ( delta &gt; 0 )
		$("#gallery ul").animate({ textIndent: -width }, delta * factorStop, "easeOutQuad");
});

Здесь я добавил еще два параметра: widthStop – ширина «тормозного пути», и factorStop — коэффициент для определения времени анимации торможения. В каждой из функций сначала находится текущее значение свойства text-indent, а затем выполняется проверка: больше ли это значение «тормозного пути». Это сделано для того, чтобы не выйти за диапазон прокрутки.

Если у вас хватило терпения правильно проделать все вышеизложенные операции, то в итоге у вас должно получиться примерно такое слайд-шоу.

Скачать рабочий пример.

Метки: , , ,