Слайдшоу с предпросмотром
Слайдшоу с предварительным просмотром миниатюр изображений. Смена слайдов может происходить, как в ручном, так и в автоматическом режиме.
HTML
Создадим два неупорядоченных списка, один для основного слайдера и один для навигации по миниатюрам.
Список "основного слайдера" будет содержать изображения и заголовки в тегах H2 и H3:
<div id="ei-slider" class="ei-slider">
<ul class="ei-slider-large">
<li>
<img src="images/large/1.jpg" alt="image01" />
<div class="ei-title">
<h2>Creative</h2>
<h3>Geek</h3>
</div>
</li>
<li>
<img src="images/large/2.jpg" alt="image02" />
<div class="ei-title">
<h2>Friendly</h2>
<h3>Devil</h3>
</div>
</li>
<li>
<img src="images/large/3.jpg" alt="image03"/>
<div class="ei-title">
<h2>Tranquilent</h2>
<h3>Compatriot</h3>
</div>
</li>
<li>
<img src="images/large/4.jpg" alt="image04"/>
<div class="ei-title">
<h2>Insecure</h2>
<h3>Hussler</h3>
</div>
</li>
<li>
<img src="images/large/5.jpg" alt="image05"/>
<div class="ei-title">
<h2>Loving</h2>
<h3>Rebel</h3>
</div>
</li>
<li>
<img src="images/large/6.jpg" alt="image06"/>
<div class="ei-title">
<h2>Passionate</h2>
<h3>Seeker</h3>
</div>
</li>
<li>
<img src="images/large/7.jpg" alt="image07"/>
<div class="ei-title">
<h2>Photography by</h2>
<h3><a target="_blank" href="http://www.behance.net/gallery/Masks/774805">Bartek Lurka</a></h3>
</div>
</li>
</ul><!-- ei-slider-large -->
<ul class="ei-slider-thumbs">
<li class="ei-slider-element">Текущий</li>
<li><a href="#">Слайд 1</a><img src="images/thumbs/1.jpg" alt="thumb01" /></li>
<li><a href="#">Слайд 2</a><img src="images/thumbs/2.jpg" alt="thumb02" /></li>
<li><a href="#">Слайд 3</a><img src="images/thumbs/3.jpg" alt="thumb03" /></li>
<li><a href="#">Слайд 4</a><img src="images/thumbs/4.jpg" alt="thumb04" /></li>
<li><a href="#">Слайд 5</a><img src="images/thumbs/5.jpg" alt="thumb05" /></li>
<li><a href="#">Слайд 6</a><img src="images/thumbs/6.jpg" alt="thumb06" /></li>
<li><a href="#">Слайд 7</a><img src="images/thumbs/7.jpg" alt="thumb07" /></li>
</ul><!-- ei-slider-thumbs -->
</div><!-- ei-slider -->
Список для навигации из миниатюр предпросмотра будет содержать абсолютный элемент (первый элемент списка с классом "ei-slider-element" и элементы списка миниатюр, содержащие анкор (ссылку) и изображение) CSS
В начале определим стиль для главной оболочки - wrapper. Слайдер будет находиться внутри wrapper, имеющей ширину 100%, чтобы занять всю ширину окна. У самого слайдера, также будет ширина 100%. Но мы установим и максимальную ширину, чтобы изображения в нашем слайдере не стали слишком широкими на больших мониторах.
.ei-slider{
position: relative;
width: 100%;
max-width: 1920px;
height: 400px;
margin: 0 auto;
}
В то время, как изображения загружаются мы будем видеть элемент отображающий процесс загрузки, который будет иметь следующий стиль:
.ei-slider-loading{
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
z-index:999;
background: rgba(0,0,0,0.9);
color: #fff;
text-align: center;
line-height: 400px;
}
Неупорядоченный список займет всё отведенное место и переполнения (выходы за пределы) показываться не будут:
.ei-slider-large{
height: 100%;
width: 100%;
position:relative;
overflow: hidden;
}
Элементы списка содержащие изображения, будут абсолютно с позиционированы. В зависимости от того, как мы перемещаемся, будем двигать слайды слева или справа
.ei-slider-large li{
position: absolute;
top: 0px;
left: 0px;
overflow: hidden;
height: 100%;
width: 100%;
}
Ширина изображения будет установлена в нашем jаvascript, но мы всё равно определим её, на случай выключенного JS:
.ei-slider-large li img{
width: 100%;
}
Контейнер заголовка будет расположен в середине элемента списка с отступом справа, чтобы подогнать изображение в нашем примере (а не перекрывать лицо фотографии):
.ei-title{
position: absolute;
right: 50%;
margin-right: 13%;
top: 30%;
}
Стиль для заголовков следующий:
.ei-title h2, .ei-title h3{
text-align: right;
}
.ei-title h2{
font-size: 40px;
line-height: 50px;
font-family: 'Playfair Display', serif;
font-style: italic;
color: #b5b5b5;
}
.ei-title h3{
font-size: 70px;
line-height: 70px;
font-family: 'Open Sans Condensed', sans-serif;
text-transform: uppercase;
color: #000;
}
У списка навигации будет маленькая высота в 13 пикселей. Значение ширины по умолчанию для миниатюр установим при инициализации нашего плагина. От той ширины установим максимальную ширину для неупорядоченного списка, что сделает навигацию эластичной при изменении размеров окна браузера, но и не займет всю ширину:
.ei-slider-thumbs{
height: 13px;
margin: 0 auto;
position: relative;
}
Элементы списка навигации будут относительно с позиционированы:
.ei-slider-thumbs li{
position: relative;
float: left;
height: 100%;
}
Специальный элемент слайдера, который указывает на текущее изображение, будет расположен абсолютно вверху элемента текущей миниатюры:
.ei-slider-thumbs li.ei-slider-element{
top: 0px;
left: 0px;
position: absolute;
height: 100%;
z-index: 10;
text-indent: -9000px;
background: #000;
background: rgba(0,0,0,0.9);
}
У элементов навигации ссылка будет иметь белую тень, чтобы немного разделить их и более темную тень под ними. Также добавим плавный переход для изменения цвета фона при наведении:
.ei-slider-thumbs li a{
display: block;
text-indent: -9000px;
background: #666 ;
width: 100%;
height: 100%;
cursor: pointer;
-webkit-box-shadow:
0px 1px 1px 0px rgba(0,0,0,0.3),
0px 1px 0px 1px rgba(255,255,255,0.5);
-moz-box-shadow:
0px 1px 1px 0px rgba(0,0,0,0.3),
0px 1px 0px 1px rgba(255,255,255,0.5);
box-shadow:
0px 1px 1px 0px rgba(0,0,0,0.3),
0px 1px 0px 1px rgba(255,255,255,0.5);
-webkit-transition: background 0.2s ease;
-moz-transition: background 0.2s ease;
-o-transition: background 0.2s ease;
-ms-transition: background 0.2s ease;
transition: background 0.2s ease;
}
.ei-slider-thumbs li a:hover{
background-color: #f0f0f0;
}
Изображение миниатюры будет расположено абсолютно с плавным переходом и отражением. Добавлением максимальной ширины у нему позволит быть уверенным в том, что миниатюра будет подогнана под размер элемента списка, когда окно браузера станет меньше, чем ширина неупорядоченного списка:
.ei-slider-thumbs li img{
position: absolute;
bottom: 50px;
opacity: 0;
z-index: 999;
max-width: 100%;
-webkit-transition: all 0.4s ease;
-moz-transition: all 0.4s ease;
-o-transition: all 0.4s ease;
-ms-transition: all 0.4s ease;
transition: all 0.4s ease;
-webkit-box-reflect:
below 0px -webkit-gradient(
linear,
left top,
left bottom,
from(transparent),
color-stop(50%, transparent),
to(rgba(255,255,255,0.3))
);
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
}
При наведении у нас будет анимироваться прозрачность и значение отступа снизу, так что будет казаться, что миниатюра выплывает сверху:
.ei-slider-thumbs li:hover img{
opacity: 1;
bottom: 13px;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
}
Наконец, что не менее важно, мы хотим быть уверенными в том, что от определенной ширины, заголовок слайда не будет перекрывать наше изображение. Мы сделаем так, что заголовок появится у основания изображения с полупрозрачным белым фоном:
@media screen and (max-width: 830px) {
.ei-title{
position: absolute;
right: 0px;
margin-right: 0px;
width: 100%;
text-align: center;
top: auto;
bottom: 10px;
background: #fff;
background: rgba(255,255,255,0.9);
padding: 5px 0;
}
.ei-title h2, .ei-title h3{
text-align: center;
}
.ei-title h2{
font-size: 20px;
line-height: 24px;
}
.ei-title h3{
font-size: 30px;
line-height: 40px;
}
}
Для случаев, когда jаvascript выключен, мы добавим этот кусочек CSS, для гарантии того, что слайды будут показаны. Навигация с миниатюрами будет скрыта:
.ei-slider{
height: auto;
}
.ei-slider-thumbs{
display: none;
}
.ei-slider-large li{
position: relative;
}
Вот и всё со стилями, перейдем к jаvascript.
JS
В начале подключаем, как обычно, jQuery, наш плагин (о нём подробнее речь пойдет ниже), плагин easing эффектов и инициализация нашего плагина с настройками:
<script type="text/jаvascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/jаvascript" src="js/jquery.eislideshow.js"></script>
<script type="text/jаvascript" src="js/jquery.easing.1.3.js"></script>
<script type="text/jаvascript">
$(function() {
$('#ei-slider').eislideshow({
easing : 'easeOutExpo',
titleeasing : 'easeOutExpo',
titlespeed : 1200
});
});
</script>
Так как мы будем делать плагин, то определим сначала его опции:
$.Slideshow.defaults = {
// типы анимации:
// "sides" : новые слайды будут появляться слева/справа
// "center": новые слайды будут появлсяться в центре
animation: 'sides', // sides || center
// если "true" - то слайды будут сменяться автоматически, и остановятся, если пользователь кликнет по миниатюре
autoplay: false,
// интервал времени для слайдшоу в мс
slideshow_interval: 3000,
// скорость анимации
speed: 800,
// эффект easing для анимации
easing: '',
// процент скорости для анимации заголовков.
titlesFactor: 0.60,
// скорость анимации заголовков
titlespeed: 800,
// эффект easing для анимации заголовков
titleeasing: '',
// максимальная ширина для миниатюр в пикселях
thumbMaxWidth: 150
};
В функции _init устанавливаем прозрачность заголовка элементов и изображений равной 0. Также предварительно загрузим изображения и после загрузки, установим их размер и положение согласно ширине и высоте слайдера. Затем сконфигурируем навигацию миниатюр, устанавливая ширину неупорядоченного списка и элементов списка.
Также покажем первый слайд и если у нас включен в опция автопоказ, то запускаем авто воспроизведение слайдшоу. Инициализируем события, которые являются событиями для изменения размеров окна и кликов по миниатюрам:
_init: function(options) {
this.options = $.extend(true, {}, $.Slideshow.defaults, options);
// установка прозрачности заголовка и изображений
this.$imgItems.css('opacity', 0);
this.$imgItems.find('div.ei-title > *').css('opacity', 0);
// index of current visible slider
this.current = 0;
var _self = this;
// загрузка изображений
// добавляем статус загрузки
this.$loading = $('<div class="ei-slider-loading">Загрузка</div>').prependTo(_self.$el);
$.when(this._preloadImages()).done(function() {
// скрываем статус загрузки
_self.$loading.hide();
// вычисляем размер и положение для каждого изображения
_self._setImagesSize();
// конфигурируем контейнер миниатюр
_self._initThumbs();
// показываем первый
_self.$imgItems.eq(_self.current).css({
'opacity': 1,
'z-index': 10
}).show().find('div.ei-title > *').css('opacity', 1);
// если автопоказ включен
if (_self.options.autoplay) {
_self._startSlideshow();
}
// инициализация событий
_self._initEvents();
});
},
А тут функции о которых мы только что говорили:
_preloadImages: function() {
// предзагрузка всех больших изображений
var _self = this,
loaded = 0;
return $.Deferred(
function(dfd) {
_self.$images.each(function(i) {
$('<img/>').load(function() {
if (++loaded === _self.itemsCount) {
dfd.resolve();
}
}).attr('src', $(this).attr('src'));
});
}
).promise();
},
_setImagesSize: function() {
// сохранить ширину ei-slider
this.elWidth = this.$el.width();
var _self = this;
this.$images.each(function(i) {
var $img = $(this);
imgDim = _self._getImageDim($img.attr('src'));
$img.css({
width: imgDim.width,
height: imgDim.height,
marginLeft: imgDim.left,
marginTop: imgDim.top
});
});
},
_getImageDim: function(src) {
var $img = new Image();
$img.src = src;
var c_w = this.elWidth,
c_h = this.$el.height(),
r_w = c_h / c_w,
i_w = $img.width,
i_h = $img.height,
r_i = i_h / i_w,
new_w, new_h, new_left, new_top;
if (r_w > r_i) {
new_h = c_h;
new_w = c_h / r_i;
} else {
new_h = c_w * r_i;
new_w = c_w;
}
return {
width: new_w,
height: new_h,
left: (c_w - new_w) / 2,
top: (c_h - new_h) / 2
};
},
_initThumbs: function() {
// set the max-width of the slider elements to the one set in the plugin's options
// also, the width of each slider element will be 100% / total number of elements
this.$sliderElems.css({
'max-width': this.options.thumbMaxWidth + 'px',
'width': 100 / this.itemsCount + '%'
});
// set the max-width of the slider and show it
this.$sliderthumbs.css('max-width', this.options.thumbMaxWidth * this.itemsCount + 'px').show();
},
_startSlideshow: function() {
var _self = this;
this.slideshow = setTimeout(function() {
var pos;
(_self.current === _self.itemsCount - 1) ? pos = 0: pos = _self.current + 1;
_self._slideTo(pos);
if (_self.options.autoplay) {
_self._startSlideshow();
}
}, this.options.slideshow_interval);
},
Функция _slideTo отвечает за переходы между слайдами. В зависимости от того, что мы указали в опциях, слайды будут появляться с какой-либо стороны или постепенно проявляться в центре. Также функция позаботится и о заголовках, которые слегка подвинем, установив для них отступы справа. Элемент миниатюры слайдера будем двигать в новую позицию соответствующую миниатюре:// показывает слайд нажатой миниатюры
_slideTo: function(pos) {
// возвращает, если нажат тот же самый элемент или анимирует
if (pos === this.current || this.isAnimating)
return false;
this.isAnimating = true;
var $currentSlide = this.$imgItems.eq(this.current),
$nextSlide = this.$imgItems.eq(pos),
_self = this,
preCSS = {
zIndex: 10
},
animCSS = {
opacity: 1
};
// новый слайд будет выезжать слевой или справой стороны
if (this.options.animation === 'sides') {
preCSS.left = (pos > this.current) ? -1 * this.elWidth : this.elWidth;
animCSS.left = 0;
}
// анимация заголовков
$nextSlide.find('div.ei-title > h2')
.css('margin-right', 50 + 'px')
.stop()
.delay(this.options.speed * this.options.titlesFactor)
.animate({
marginRight: 0 + 'px',
opacity: 1
}, this.options.titlespeed, this.options.titleeasing)
.end()
.find('div.ei-title > h3')
.css('margin-right', -50 + 'px')
.stop()
.delay(this.options.speed * this.options.titlesFactor)
.animate({
marginRight: 0 + 'px',
opacity: 1
}, this.options.titlespeed, this.options.titleeasing)
$.when(
// плавное появление текущих заголовков
$currentSlide.css('z-index', 1).find('div.ei-title > *').stop().fadeOut(this.options.speed / 2, function() {
// перезагрзить стили
$(this).show().css('opacity', 0);
}),
// анимировать следующий слайд
$nextSlide.css(preCSS).stop().animate(animCSS, this.options.speed, this.options.easing),
// "sliding div" двигать в новую позицию
this.$sliderElem.stop().animate({
left: this.$thumbs.eq(pos).position().left
}, this.options.speed)
).done(function() {
// перезагрузить значения
$currentSlide.css('opacity', 0).find('div.ei-title > *').css('opacity', 0);
_self.current = pos;
_self.isAnimating = false;
});
},
Функция _initEvents пересчитает размеры изображений, когда мы изменим размеры окна браузера и пере позиционирует элемент миниатюры:_initEvents: function() {
var _self = this;
// изменяем размер окна
$(window).on('smartresize.eislideshow', function(event) {
// изменяем размер изображений
_self._setImagesSize();
// перезагружаем положение миниатюр div
_self.$sliderElem.css('left', _self.$thumbs.eq(_self.current).position().left);
});
// клик по миниатюре
this.$thumbs.on('click.eislideshow', function(event) {
if (_self.options.autoplay) {
clearTimeout(_self.slideshow);
_self.options.autoplay = false;
}
var $thumb = $(this),
idx = $thumb.index() - 1; // exclude sliding div
_self._slideTo(idx);
return false;
});
}
};
Вот и всё.