Блог для начинающих веб разработчиков. HTML, СSS, Jquery, Drupal и другое.

→ Простой jQuery слайдер . Часть 2.

Опубликовано: 06 мая 2012

Добрый день всем читателям и подписчикам heavenweb.ru. В одной их прошлых статей я рассказывал как сделать несложный jQuery слайдер. Его код был компактным и простым, однако, скрипт имел некоторые недостатки. В этой статье мы рассмотрим как можно расширить возможности скрипта, и исправим некоторые баги. Смотрите демо ниже:

ДемоСкачать

 

Итак, какие возможности нам хотелось бы добавить во вторую версию HWSlider?

  • Во первых, хотелось бы иметь возможность вставить несколько таких слайдеров на странице. Иногда возникает такая необходимость, например в первом блоке прокручиваются какие-нибудь баннеры, а во втором – какие-то анонсы статей (текст). Соответственно, нужно предусмотреть возможность оформить каждый слайдер индивидуально.
  • Во вторых, не всегда нужна автоматическая смена слайдов. Нужно дать возможность администратору отключить авто прокрутку в любом из слайдеров.
  • В первой версии HWSlider была возможность отключить ссылки «следующий» и «предыдущий», но не было возможности отключить кнопки перехода на каждый слайд (ещё их называют буллеты).

Ну что-же, с требованиями определились, начнём дорабатывать наш скрипт.

Начнём с html. В старой версии мы использовали основной тег с идентификатором #slider-wrap. Если слайдеров будет несколько, то мы не сможем вставить несколько таких тегов, ведь по правилам HTML, не может быть нескольких элементов с одинаковым атрибутом id (то есть с одинаковым идентификатором). Тогда используем вместо них классы.

Например, создадим два слайдера. Пусть в первом крутятся те же изображения, а во втором будет текст.

<div class="slider-wrap slide-1">
	<div class="slider">
		<div class="slide"><img src="img/001.jpg" width="640" height="360"></div>
		<div class="slide"><img src="img/002.jpg" width="640" height="360"></div>
		<div class="slide"><img src="img/003.jpg" width="640" height="360"></div>
		<div class="slide"><img src="img/004.jpg" width="640" height="360"></div>
	</div>
</div>

<div class="slider-wrap slide-2">
	<div class="slider">
		<div class="slide">Слайд 1</div>
		<div class="slide">Слайд 2</div>
		<div class="slide">Слайд 3</div>
		<div class="slide">Слайд 4</div>
	</div>
</div>

Структура похожа на то, что было раньше, только все идентификаторы заменены одноимёнными классами. А так же к каждому div-у с классом slider-wrap мы назначили ещё один (slide-1 и slide-2), чтобы с помощью CSS оформить каждый слайдер по отдельности.

Теперь рассмотрим CSS. Здесь тоже не очень много изменений:

.slide-1{ /* Оболочка слайдера и кнопок */
	width:660px; 
	}
.slide-1 .slider{ /* Оболочка слайдера */
	width:640px;
	height:360px;
	overflow: hidden;
	border:#eee solid 10px;
	position:relative;}
.slide-1 .slide{ /* Слайд */
	width:auto;
	height:100%;
	}
.sli-links{ /* Кнопки смены слайдов */
	margin-top:10px;
	text-align:center;}
.sli-links .control-slide{
	margin:2px;
	display:inline-block;
	width:16px;
	height:16px;
	overflow:hidden;
	text-indent:-9999px;
	background:url(radioBg.png) center bottom no-repeat;}
.sli-links .control-slide:hover{
	cursor:pointer;
	background-position:center center;}
.sli-links .control-slide.active{
	background-position:center top;}
.prewbutton, .nextbutton{ /* Ссылка "Следующий" и "Предыдущий" */
	display:block;
	width:15px;
	height:100%;
	position:absolute;
	top:0;
	overflow:hidden;
	text-indent:-999px;
	background:url(arrowBg.png) left center no-repeat;
	opacity:0.8;
	z-index:3;
	outline:none !important;}
.prewbutton{left:10px;}
.nextbutton{
	right:10px;
	background:url(arrowBg.png) right center no-repeat;}
.slide-1 .prewbutton:hover, .nextbutton:hover{
	opacity:1;}
	
/* Второй слайдер */
.slide-2{
	width:500px;
	font:normal 12px/15px Georgia, "Times New Roman", Times, serif; 
	}
.slide-2 .slider{
	height:250px;
	overflow: hidden;
	border:#888 solid 10px;
	position:relative;
	background:#CCCCCC;}
.slide-2 .slide{
	padding:10px 40px;
	}
/* Второй слайдер - конец */

Основное это то, что мы добавили стилей для второго слайдера, отличных от стилей первого. Второй блок по размеру будет меньше (500x250 пикселей), и будет отличаться цветом фона и границ. Ну и конечно, везде вместо идентификаторов – классы.

Далее JavaScript код. Он получился несколько объемнее и запутаннее, поэтому в код я вставил комментарии.

/*  Примечание: Вставьте этот скрипт в свой js - файл */
(function ($) {
$(document).ready(function(e) {
/*  Настройки Слайдера: */
var mainConfig = new Array();

/* Для каждого слайдера (div-а с классом slider-wrap) необходимо создать новый элемент
   массива mainConfig[X], где X - порядковый номер слайдера на странице (по коду,
   начиная с нуля).
   Если элементов массива больше чем слайдеров, скрипт работает исправно, ошибок не возникает.
   По умолчанию уже создано 5 элементов (для 5 слайдеров).
*/

mainConfig[0] = {
	hwSlideSpeed: 400, // Скорость анимации смены слайда.
	hwTimeOut: 10000, // Задержка автоматической прокрутки.
	hwNeedLinks: true, // true - если нужны ссылки вперёд-назад, false - если не нужны.
	hwNeedBullets: true, // true - если нужны кнопки перехода на каждый слайд, иначе - false
	hwAutoRotate: true // true - автоматическая прокрутка включена, false - выключена.
	}
mainConfig[1] = {
	hwSlideSpeed: 400,
	hwTimeOut: 10000,
	hwNeedLinks: true,
	hwNeedBullets: false,
	hwAutoRotate: false
	}
mainConfig[2] = {
	hwSlideSpeed: 400,
	hwTimeOut: 10000,
	hwNeedLinks: true,
	hwNeedBullets: true,
	hwAutoRotate: false
	}
mainConfig[3] = {
	hwSlideSpeed: 400,
	hwTimeOut: 10000,
	hwNeedLinks: true,
	hwNeedBullets: true,
	hwAutoRotate: false
	}
mainConfig[4] = {
	hwSlideSpeed: 400,
	hwTimeOut: 10000,
	hwNeedLinks: true,
	hwNeedBullets: true,
	hwAutoRotate: false
	}
var activeSlide = new Array();
var slideCount = new Array();
var timerid = new Array();
var neddRotatr = new Array();
	
/* Для каждого .slider-wrap  */
$('.slider-wrap').each(function(index) {
	var mainThis = $(this)
	slideCount[index] = $(".slide", mainThis).size();
	activeSlide[index] = 0;
	$('.slide', mainThis).css({"position" : "absolute", "top":'0', "left": '0'}).hide().eq(0).show();
	
/* Добавляем ссылки Назад - Вперёд, если они нужны */
if(mainConfig[index].hwNeedLinks){
	var $linkArrow = '<a class="prewbutton" href="#"><</a><a class="nextbutton" href="#">></a>';	 
	$(".slider", mainThis).prepend($linkArrow);
}

/* Добавляем ссылки на слайды (буллеты), если они нужны */
if(mainConfig[index].hwNeedBullets){
var $adderSpan = '';
	$('.slide', mainThis).each(function(num) {
			$adderSpan += '<span class = "control-slide">' + num + '</span>';
		});
	$(mainThis).append('<div class = "sli-links">' + $adderSpan +'</div>');
	$(".control-slide:first", mainThis).addClass("active");	
}

/* Обработчики ссылок */
$('.nextbutton', mainThis).click(function(){
		animSlide(index, "next");
		return false;
		})
		
$('.prewbutton', mainThis).click(function(){
		animSlide(index, "prew");
		return false;
		})
 
$('.control-slide', mainThis).click(function(){
	var goToNum = parseFloat($(this).text());
	animSlide(index, goToNum);
	});	
	
/* Включаем автоматическую прокрутку, если она нужна, с паузой при наведении курсора на слайдер.
   Используем jQuery плагин timers.
 */
if(mainConfig[index].hwAutoRotate){
mainThis.everyTime(mainConfig[index].hwTimeOut, timerid[index], function(){animSlide(index, 'next');});	
mainThis.hover(
function(){mainThis.stopTime(timerid[index]);},
function(){mainThis.everyTime(mainConfig[index].hwTimeOut, timerid[index], function(){animSlide(index, 'next');});}	
	);
}
	});
/* Для каждого .slider-wrap - конец */
	
/* Функция прокрутки */
var animSlide = function(id, arrow){
	var $containerNum = $('.slider-wrap').eq(id).find(".slide");
	var activeVar = activeSlide[id];
	var countVar = slideCount[id];
/* Запускаем анимацию только если выбран другой слайд (не показывающийся в данный момент). */
if(activeVar != arrow){ 
	$containerNum.eq(activeVar).fadeOut(mainConfig[id].hwSlideSpeed);
	$('.slider-wrap').eq(id).find(".control-slide").eq(activeVar).removeClass("active");
	if(arrow == "next"){
			if(activeVar == (countVar-1)){activeVar=0;}
			else{activeVar++}
		}
	else if(arrow == "prew")
		{
			if(activeVar == 0){activeVar=countVar-1;}	
			else{activeVar-=1}
		}
	else{
			activeVar = arrow;
		}
	$containerNum.eq(activeVar).fadeIn(mainConfig[id].hwSlideSpeed);
	activeSlide[id] = activeVar;
	$('.slider-wrap').eq(id).find(".control-slide").eq(activeVar).addClass("active");
	}}
/* Функция прокрутки - Конец */
});
})(jQuery);

Давайте разберёмся как он работает поподробнее.

Во первых настройки. Так как слайдеров много, то настройки нужны для каждого по отдельности.

Вместо переменных удобнее использовать объекты. Каждому слайдеру соответствует один элемент массива mainConfig[X], где X – порядковый номер слайдера на странице (начинается с 0). Как видно, по умолчанию задано 5 элементов массива, то есть можно разместить сразу 5 слайдеров. Конечно, можно по аналогии добавить новых элементов и создать столько слайдеров, сколько вам угодно.

Далее мы используем jQuery метод .each(), который выполняет код заключённый в фигурные скобки столько раз, сколько встретит на странице элементов «.slider-wrap». Причём, при каждом выполнении кода, значение index, передаваемое в функцию будем меняться (0,1,2, … и.т.д), а так же каждый раз переменная this будет ссылаться на каждый из этих div-ов. Используем эту возможность, для создания всех ссылок предназначенных для управления скриптом, и вешаем обработчики на эти элементы.

Значительному изменению подверглась функция прокрутки. Вместо javascript функций, на мой взгляд целесообразнее использовать плагин timers для jQuery. Он позволяет использовать нам два метода: .everyTime() и .stopTime(). Подробнее о их работе можно прочитать в этой статье на Хабре. Это более удобные реализации таймеров (setTimeout и clrearTimeout). Мы создаём отдельный таймер для каждого слайдера, в результате мы больше не нуждаемся в замыкании внутри функции анимации. И конечно, не забываем об остановке смены слайдов, при наведении курсора на блок. Обратите внимание, что для использования этих функций, нужно подключить ещё один файл jquery.timers.js  - тот самый плагин.

Функция прокрутки animSlide не сильно изменилась. Только теперь в неё нужно передать не просто направление смены слайдов, но и номер блока-слайдера.

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

Таким образом, мы реализовали все новые требования. Посмотреть демо HWSlider2, а так-же скачать все необходимые исходники, можно по ссылкам ниже.

ДемоСкачать

Спасибо за прочтение статьи. Хотелось бы увидеть в комментариях, что вы думаете об этом скрипте, была ли эта информация полезна для вас?

А так же предлагаю подписаться на RSS, чтобы своевременно получать обновления блога.

Поделиться:
Комментарии

Да, спасибо, помогло очень. ) Буду колупать под свои нужды. Загляну еще:)

Акс
вт, 2012-08-21 02:03

Очень полезная статья - спасибо огромное! Весьма кстати пришлась - как раз сейчас тоже ковыряю слайдер на jquery, затачивая под свои нужды.

Дмитрий
сб, 2012-11-17 21:29

Спасибо за похвалу, я бы сейчас немного ещё оптимизировал его работу, сделал в виде плагина, но времени к сожалению нет совсем :)

Faraday
вс, 2012-11-18 15:51

Спасибо

Так
пн, 2012-11-26 00:44

Спасибо за интересный слайдер. А за подробные комментарии - отдельное спасибо, ибо есть с чем поработать самостоятельно...=) Однозначно, в закладки!

Сандр
пн, 2012-11-26 16:17

Спасибо, руководство очень помогло! Не могли бы вы подсказать какие параметры добавить чтобы слайды показывались рандомно и с задержкой между сменой. Заранее спасибо!

AronVit
пн, 2012-11-26 16:42

Здравствуйте. Думаю придётся вносить изменения в функцию animSlide для добавления новых возможностей.
В данном скрипте к сожалению такую возможность я не предусматривал :)

Faraday
пт, 2013-01-04 21:04

Здравствуйте.
Подскажите пожалуйста, как сделать отдельно текстовый слайдер с автоматической прокруткой ?

Евгений
пн, 2012-12-31 18:26

Добрый день. А в чём проблемма? Вместо картинок, подставьте любой текст. Посмотрите в примере второй слайдер. Он текстовой.

В конфигурации для слайдера установите:



mainConfig[0] = {
    hwSlideSpeed: 400,
    hwTimeOut: 10000,
    hwNeedLinks: true, 
    hwNeedBullets: true,
    hwAutoRotate: true // Здесь true значит автоматическая прокрутка включена.
    }

Параметр hwAutoRotate включает или отключает автопрокрутку.

Faraday
пт, 2013-01-04 21:01

А как свою навигацию прикрутить?

Антон
вт, 2013-03-05 00:32

Как избавиться от появления '#' хэша в строке адреса, при переключении слайдов.

Сергей
пт, 2013-03-08 00:47

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

Антон
сб, 2013-03-09 08:54

Слайдер поддерживает масштабирование (чтобы с уменьшением размера экрана, слайдер мог менять свой размер)?

redmol
вт, 2013-03-12 22:54

Доброго времени суток!
Извиняюсь сразу за вопрос, нервов не хватает, в js не силен никак, уж простите. Нужна ваша помощь, суть сделать остановку слайдера(того что ниже) при наведении курсора, если это возможно.

<script type="text/javascript">

window.addEvent('domready', function() { $('gantry-totop').store('tip:text', '');});

window.addEvent('domready', function() {
var modules = ['rt-block'];
var header = ['h3','h2','h1'];
GantryBuildSpans(modules, header);
});

window.addEvent('domready', function() {
new Fusion('ul.menutop', {
pill: 0,
effect: 'slide and fade',
opacity: 0.92,
hideDelay: 500,
centered: 0,
tweakInitial: {'x': -10, 'y': -9},
tweakSubsequent: {'x': 0, 'y': 0},
tweakSizes: {'width': 20, 'height': 20},
menuFx: {duration: 400, transition: Fx.Transitions.Quad.easeOut},
pillFx: {duration: 400, transition: Fx.Transitions.Back.easeOut}
});

});
window.addEvent('load', function() {
});
try {$Gavick;}catch(e){$Gavick = {};};$Gavick["gkIs-gk-is-193"] = { "anim_speed": 800, "anim_interval": 8000, "autoanimation": 1, "anim_type": "top" };
</script>
<script type="text/javascript">window.addEvent( 'domready', function() { $$('.album').multiFade(.22);});</script>

Алексей
чт, 2013-03-14 05:42

Огромное спасибо автору! Очень долго пытался найти в Интернете работающий слайдер с использованием классов. БОЛЬШОЕ СПАСИБО!!!

Максим
сб, 2013-03-30 21:06

Установил слайдер, радиобаттаны работают, а кнопки перелистывания - нет. Подскажите, пожалуйста, как исправить.

Игорь
вт, 2013-04-16 17:04

В дополнении к вопросу: подскажите пожалуйста, какие стили нужны, чтоб радиобаттаны разместить поверх слайдов.

Игорь
вт, 2013-04-16 17:20

М, ну можно в принципе диву с классом sli-links дать абсолютное позиционирование, и как-нибудь подвинуть свойствами top и left, но тогда диву slider-wrap обязателельно нужно установить position: relative;

Могут быть ещё нюансы, надо смотреть.

Faraday
пн, 2013-04-29 12:22

Проверьте соответствие классов и идентификаторов в html-разметке, или дайте ссылку на сайт с проблеммой.

Faraday
пн, 2013-04-29 12:19

Спасибо за статью все понятно, а можно как нибудь дополнить чтобы фото могли быть подписанными например тут: http://manual.ucoz.net/board/10-2-0-462-0-0-0-0-1366125532
1 пример. мне вот очень нужно это, заранее СПАСИБО!!!

Юлия
пт, 2013-04-26 16:37

Это не сложно, можно добавить внутрь слайда помимо картинки блок с текстом. А с помощью CSS сделать так, чтобы он был над картинкой. (т.е. абсолютное позиционирование + z-index выше чем у картинки)

Faraday
пн, 2013-04-29 12:24

Большое спасибо. Очень помогло.

Sphyrus
чт, 2013-05-09 11:53

Спасибо за статью!
Почему-то не получается сделать каждую картинку ссылкой на другую html-страницу. Обычный тег на картинке в слайдере не работает.

Анатолий
ср, 2013-08-07 21:47

Добрый день. Не могу подключить скрипт в вордпресс. Был бы рад помощи.

Павел
пт, 2013-09-20 10:08

Добрый день нужна ваша помощь в настройке вашего слайдера на вордпресс. Могу заплатить. Напишите мне))

Павел
пт, 2013-09-20 10:25

Спасибо, отличный слайдер с хорошо разжеванным разъяснением принципа работы)

P.S. Было бы круто в конфиге указывать тип анимации. В будущем можно будет доработать) Еще раз спасибо, очень полезная штука)

Роман
пт, 2013-09-20 20:25

Добрый день, а возможно ли сделать этот слайдер адаптивным? хотелось бы узнать как?

Роман
ср, 2014-02-05 16:45

Роман, насчет адаптивности слайдера - нужно сделать вместо:

<div class="slide"><img src="img/001.jpg" width="640" height="360"></div>

Такой вариант:

<div class="slide" style="background-image: url(img/001.jpg); display: block; background-position: 50% 0%; background-repeat: repeat no-repeat;">

и style.css:

*{
margin: 0;
padding: 0;
}

#slider-wrap { /* Оболочка слайдера и кнопок */
width:100%;
height: 100%;
}

#slider { /* Оболочка слайдера */
width:100%;
height:700px;
overflow: hidden;
position:relative;
}

.slide { /* Слайд */
width:100%;
height:100%;
}
...
beta
вт, 2014-03-04 19:41

"буллеты" не отображаются в ie10 и ie7

artyom
вс, 2014-03-09 22:04

Здравствуйте! не подскажите, как поменять анимацию смены слайдов?

Андрей
чт, 2014-08-28 06:04

Добрый день. Думаю для другого типа анимации, придётся много кода менять, так сразу не скажу :)

Faraday
пн, 2014-09-01 23:24

Здравствуйте)
Огромное спасибо за код и отличное объяснение.
Сейчас переделываю на свой слайдер и буллеты должны быть цыфрами 1, 2, 3. У меня же получается рабочий слайдер с 0, 1, 2.
Подскажите, пожалуйста, как это исправить?
Спасибо.

Ирина
ср, 2014-09-03 13:35

И вам не хворать :) А вы просто убираете CSS свойства?. Тогда первая мысль которая приходит в голову, это в JS коде добавить один в функцию добавления буллетов, будет вот так (там num+1 в скобках отличие):

if(mainConfig[index].hwNeedBullets){
var $adderSpan = '';
	$('.slide', mainThis).each(function(num) {
			$adderSpan += '<span class = "control-slide">' + (num+1) + '</span>';
		});
	$(mainThis).append('<div class = "sli-links">' + $adderSpan +'</div>');
	$(".control-slide:first", mainThis).addClass("active");	
}

и ещё убрать единицу в обработчике этих ссылок. Вот так например:

$('.control-slide', mainThis).click(function(){
	var goToNum = parseFloat($(this).text());
	animSlide(index, (goToNum-1));
	});	

Вроде должно работать, возможно есть лучший способ, но надо думать :)

Faraday
пт, 2014-09-05 19:29

Да, работает!!!)))
Огромное-огромное спасибо Вам за помощь.
Ваш сайт для меня просто находка, много чего нового узнала)
Вы молодец, а Ваш труд бесценен.

Ирина
сб, 2014-09-06 12:59

Отличная статья! спасибо за ваш труд!
был бы очень рад если бы вы разобрали принцип работы данного слайдера - http://www.jssor.com/demos/nearby-image-partial-visible-slider.html
кода очень много и для новичка разобраться тяжело

Владимир
чт, 2014-09-11 21:32

Вставил код слайдера и поменял фотки (3шт.), а буллетов почему-то больше и все они пустые! Что делать - не знаю.

http://navozorazbrasyvatel.rutrucks.com/

Иван
пн, 2015-02-02 14:24

P.S. точнее не все, а те, которые лишние, т.е. 3 работающих и 3 пустых.

Иван
пн, 2015-02-02 14:54

Дай тебе бог здоровья, добрый человек! Отличный слайдер! Низкий поклон и большая человеческая благодарность!

Сергей
пт, 2015-07-03 17:00

добрый день!
скажите, пожалуйста, как сделать более плавное появление нового слайда?
при увеличении значения hwSlideSpeed исчезновение замедляется, но новый слайд всё так же резко появляется?
также скрытие последнего слайда происходит достаточно резко, если переходить к первому

crunchy
пт, 2016-02-12 21:04

Здравствуйте!
Скажите, пожалуйста, если в скрипте делать не mainConfig[0], а, например, mainConfig[side], то в html не , а , и всё будет работать правильно? Т.е. в mainConfig[0] - 0 это некий идентификатор?
Благодарю!

Name
пт, 2017-10-20 16:26
Комментировать