Предпросмотр миниатюр слайдами
В этом уроке я покажу, как можно сделать предпросмотр миниатюр слайдами на jQuery.
HTML
Структура HTML будет построена из контейнера - списка, который будет включать в себя элементы ввиде точек и специальный элемент списка для миниатюр. Специальный элемент списка будет иметь класс "ts_thumbnails" и будет содержать элемент с маленьким окном, в котором мы будем видеть миниатюры, как только наведем курсор на точку.
<ul class="ts_container">
<li><a href="#">Image 1</a></li>
<li><a href="#">Image 2</a></li>
<li><a href="#">Image 3</a></li>
<li><a href="#">Image 4</a></li>
<li><a href="#">Image 5</a></li>
<li><a href="#">Image 6</a></li>
<li><a href="#">Image 7</a></li>
<li><a href="#">Image 8</a></li>
<li><a href="#">Image 9</a></li>
<li><a href="#">Image 10</a></li>
<li class="ts_thumbnails">
<div class="ts_preview_wrapper">
<!-- List with thumbnails/preview items -->
</div>
<span></span>
</li>
</ul>
Пустой тег <span> будет содержать маленький треугольник, который указывает на текущую точку. Список миниатюр, который будет внутри DIV с классом "ts_preview_wrapper" будет иметь следующий вид:
<ul class="ts_preview">
<li><img src="images/thumbs1/1.jpg" alt="Thumb 1" /></li>
<li><img src="images/thumbs1/2.jpg" alt="Thumb 2" /></li>
<li><img src="images/thumbs1/3.jpg" alt="Thumb 3" /></li>
<li><img src="images/thumbs1/4.jpg" alt="Thumb 4" /></li>
<li><img src="images/thumbs1/5.jpg" alt="Thumb 5" /></li>
<li><img src="images/thumbs1/6.jpg" alt="Thumb 6" /></li>
<li><img src="images/thumbs1/7.jpg" alt="Thumb 7" /></li>
<li><img src="images/thumbs1/8.jpg" alt="Thumb 8" /></li>
<li><img src="images/thumbs1/9.jpg" alt="Thumb 9" /></li>
<li><img src="images/thumbs1/10.jpg" alt="Thumb 10" /></li>
</ul>
CSS
Основной контейнер - список будет иметь относительное позиционирование и его ширина будет равна сумме ширин всех точек.
ul.ts_container{
list-style:none;
margin:0;
padding:0;
width:170px;
margin:20px auto;
position:relative;
height:17px;
}
Как мы увидим позже, ширина точки 11px + отступ (padding) с каждой стороны 3px. Если вы будете использовать более 10 точек, то необходимо будет изменить значение ширины (а также и высоты) с учетом всех элементов.Элементы списка, например точки, будут располагаться слева:
ul.ts_container li{
float:left;
}
В качестве точек используется фоновая картинка, и текст имеет параметр indent:-9000px, чтобы его не было видно:ul.ts_container li a{
display:block;
text-indent:-9000px;
width:11px;
height:11px;
outline:none;
padding:0px 3px;
background:transparent url(../images/sliderIcons/dot.png) no-repeat top center;
}
При наведении курсора на точку изменяется положение фонового изображения так, что мы увидим его нижнюю часть, т. е. из светло-серой точка станет серой.
ul.ts_container li a:hover,
ul.ts_container li.selected a{
background-position:50% -11px;
}
Последний элемент списка, который является специальным контейнером миниатюр будет иметь абсолютное позиционирование и изначально он будет не видимым.ul.ts_container li.ts_thumbnails{
display:none;
position:absolute;
}
Пустой тег <span> содержащий маленький треугольник, будет позиционироваться динамически, т.к. зависит от размера миниатюры.ul.ts_container li.ts_thumbnails span{
background:transparent url(../images/sliderIcons/triangle.png) no-repeat top center;
width:15px;
height:6px;
position:absolute;
}
Совет: Если вы считаете, что не очень удобно использовать в HTML пустые элементы, то просто добавьте какой то осмысленный текст, и добавьте значение text-indent с минусовым значением, чтобы текст не был виден. Теперь HTML будет более удобен для понимания.Превьюшки будут обрамлены белой рамочкой с тенью. Размеры, опять же, формируются динамически, так как зависят от размера картинок. Выходы элементов за пределы рамки будут скрыты,так как будет ряд миниатюр в списке внутри этой рамочки:
.ts_preview_wrapper{
border:5px solid #fff;
overflow:hidden;
position:relative;
-moz-box-shadow:0px 0px 5px #999;
-webkit-box-shadow:0px 0px 5px #999;
box-shadow:0px 0px 5px #999;
}
Список всех миниатюр будет иметь абсолютное позиционирование:ul.ts_preview{
position:absolute;
left:0px;
top:0px;
margin:0;
padding:0;
list-style-type:none;
}
Список элементов содержащие миниатюры будет придерживаться левой стороны:ul.ts_preview li{
float:left;
}
Миниатюры должны показываться, как блоки:
ul.ts_preview li img{
display:block;
}
JS
Основная идея этого эффекта, чтобы была возможность его использования с миниатюрами любого разумного размера. Для этого был сделан следующий плагин:
(function($) {
$.fn.thumbnailSlider = function(options) {
var opts = $.extend({}, $.fn.thumbnailSlider.defaults, options);
return this.each(function() {
...
});
};
$.fn.thumbnailSlider.defaults = {
speed : 100, //скорость анимации каждого слайда
easing : 'jswing', //легкий эффект для анимации слайда
thumb_width : 75, //ширина ваших фоток
thumb_height: 75, //высота ваших фоток
zoom : false, //анимация увеличения для миниатюр
zoomratio : 1.3, //множитель для увеличения (должен быть > 1)
zoomspeed : 15000, //скорость анимации увеличения
onclick : function(){return false;} //вызов по клику
};
})(jQuery);
Посмотрим на работу плагина более подробно. Во-первых, нужно определить несколько переменных:var $this = $(this),
o = $.meta ? $.extend({}, opts, $pxs_container.data()) : opts;
var $ts_container = $this.children('.ts_container'),
$ts_thumbnails = $ts_container.children('.ts_thumbnails'),
$nav_elems = $ts_container.children('li').not($ts_thumbnails),
total_elems = $nav_elems.length,
$ts_preview_wrapper = $ts_thumbnails.children('.ts_preview_wrapper'),
$arrow = $ts_thumbnails.children('span'),
$ts_preview = $ts_preview_wrapper.children('.ts_preview');
Вычисление значения размеров для контейнера ts_thumbnails:/*
calculate sizes for $ts_thumbnails:
width -> width thumbnail + border (2*5)
height -> height thumbnail + border + triangle height(6)
top -> -(height plus margin of 5)
left -> leftDot - 0.5*width + 0.5*widthNavDot
this will be set when hovering a dot,
and the default value will correspond to the first nav dot
*/
var w_ts_thumbnails = o.thumb_width + 2*5,
h_ts_thumbnails = o.thumb_height + 2*5 + 6,
t_ts_thumbnails = -(h_ts_thumbnails + 5),
$first_nav = $nav_elems.eq(0),
l_ts_thumbnails = $first_nav.position().left - 0.5*w_ts_thumbnails + 0.5*$first_nav.width();
Теперь нужно установить эти значения:$ts_thumbnails.css({
width : w_ts_thumbnails + 'px',
height : h_ts_thumbnails + 'px',
top : t_ts_thumbnails + 'px',
left : l_ts_thumbnails + 'px'
});
Следующий шаг это правильное позиционирование треугольника: /*
calculate the top and left for the triangle/tooltip
top -> thumb height + border(2*5)
left -> (thumb width + border)/2 -width/2
*/
var t_arrow = o.thumb_height + 2*5,
l_arrow = (o.thumb_width + 2*5) / 2 - $arrow.width() / 2;
$arrow.css({
left : l_arrow + 'px',
top : t_arrow + 'px',
});
Список ts_preview, который содержит все миниатюры, нуждается в задании ширины, которую мы вычислим путём умножения ширины миниатюры на общее количество миниатюр:/*
calculate the $ts_preview width -> thumb width times number of thumbs
*/
$ts_preview.css('width' , total_elems*o.thumb_width + 'px');
Затем мы устанавливаем его ширину и высоту:$ts_preview_wrapper.css({
width : o.thumb_width + 'px',
height : o.thumb_height + 'px'
});
Теперь определим, что будет происходить при наведении на элемент навигации, то есть в нашем случае на точки.Если используется опция увеличения, то будет увеличиваться ширина и высота миниатюры:
$nav_elems.bind('mouseenter',function(){
var $nav_elem = $(this),
idx = $nav_elem.index();
/*
calculate the new left
for $ts_thumbnails
*/
var new_left = $nav_elem.position().left - 0.5*w_ts_thumbnails + 0.5*$nav_elem.width();
$ts_thumbnails.stop(true)
.show()
.animate({
left : new_left + 'px'
},o.speed,o.easing);
/*
animate the left of the $ts_preview to show the right thumb
*/
$ts_preview.stop(true)
.animate({
left : -idx*o.thumb_width + 'px'
},o.speed,o.easing);
//zoom in the thumb image if zoom is true
if(o.zoom && o.zoomratio > 1){
var new_width = o.zoomratio * o.thumb_width,
new_height = o.zoomratio * o.thumb_height;
//increase the $ts_preview width in order to fit the zoomed image
var ts_preview_w = $ts_preview.width();
$ts_preview.css('width' , (ts_preview_w - o.thumb_width + new_width) + 'px');
$ts_preview.children().eq(idx).find('img').stop().animate({
width : new_width + 'px',
height : new_height + 'px'
},o.zoomspeed);
}
}).bind('mouseleave',function(){
//if zoom set the width and height to defaults
if(o.zoom && o.zoomratio > 1){
var $nav_elem = $(this),
idx = $nav_elem.index();
$ts_preview.children().eq(idx).find('img').stop().css({
width : o.thumb_width + 'px',
height : o.thumb_height + 'px'
});
}
$ts_thumbnails.stop(true)
.hide();
}).bind('click',function(){
var $nav_elem = $(this),
idx = $nav_elem.index();
o.onclick(idx);
});