В этом уроке мы с Вами создадим слайдер изображений с небольшим поворотом картинок с использованием библиотеки jQuery и CSS3. В сети можно встретить невероятное количество разных слайдеров, но такого вы еще не видели!
Придадим слайдеру ассиметричный вид с помощью креативного расположения элементов и использования границ различной толщины. Кроме того, добавим возможность автоматической прокрутки изображений (чтобы пользователю не было нужды нажимать на кнопки пролистывания изображений), а также поддержку колесика мышки. Мы не будем изобретать велосипед и воспользуемся для поворота изображения плагином jQuery 2D Transformation, а для колесика мыши - jQuery Mousewheel.
Для начала обернем наш слайдер и присвоим нашей обертке класс rmwrapper
:
<div class="rm_wrapper">
...
</div>
Внутри этой обертки у нас будет находиться контейнер для текущих изображений слайдера, маски и угловые элементы, а также заголовок и скрытый div, который будет содержать остальные изображения:
<div id="rm_container" class="rm_container">
<ul>
<li data-images="rm_container_1" data-rotation="-15">
<img src="images/1.jpg"/>
</li>
<li data-images="rm_container_2" data-rotation="-5">
<img src="images/2.jpg"/>
</li>
<li data-images="rm_container_3" data-rotation="5">
<img src="images/3.jpg"/>
</li>
<li data-images="rm_container_4" data-rotation="15">
<img src="images/4.jpg"/>
</li>
</ul>
<div id="rm_mask_left" class="rm_mask_left"></div>
<div id="rm_mask_right" class="rm_mask_right"></div>
<div id="rm_corner_left" class="rm_corner_left"></div>
<div id="rm_corner_right" class="rm_corner_right"></div>
<h2>Dior</h2>
<div style="display:none;">
<div id="rm_container_1">
<img src="images/1.jpg"/>
<img src="images/5.jpg"/>
<img src="images/6.jpg"/>
<img src="images/7.jpg"/>
</div>
<div id="rm_container_2">
<img src="images/2.jpg"/>
<img src="images/8.jpg"/>
<img src="images/9.jpg"/>
<img src="images/10.jpg"/>
</div>
<div id="rm_container_3">
<img src="images/3.jpg"/>
<img src="images/11.jpg"/>
<img src="images/12.jpg"/>
<img src="images/13.jpg"/>
</div>
<div id="rm_container_4">
<img src="images/4.jpg"/>
<img src="images/14.jpg"/>
<img src="images/15.jpg"/>
<img src="images/16.jpg"/>
</div>
</div>
</div>
Показываемый в данный момент комплект изображений будет содержать следующую необходимую нам информацию: угол, на который необходимо поворачивать изображение, какие изображения необходимо выводить дальше. Маска и угловые div
будут абсолютно позиционированны и расположенны на верху слайдера. Также их необходимо слегка повернуть, чтобы закрыть некоторые области. После этого добавим элементы навигации и кнопку, запускающую автоматичесую смену изображений:
<div class="rm_nav">
<a id="rm_next" href="#" class="rm_next"></a>
<a id="rm_prev" href="#" class="rm_prev"></a>
</div>
<div class="rm_controls">
<a id="rm_play" href="#" class="rm_play">Запустить</a>
<a id="rm_pause" href="#" class="rm_pause">Остановить</a>
</div>
Пришло время заняться CSS
стилями. Для начала сбросим дефолтные настройки блоков, прошитые в браузерах и определим свойства для тега body.
Примечание: Если вы захотите изменить цвет фона основного экрана, то необходимо также поменять цвет фона и цвет границ элементов слайдера.
@import url('reset.css');
body{
background:#f0f0f0;
color:#000;
font-family: Arial, sans-serif;
font-size:16px;
}
a{
color:#000;
text-decoration:none;
}
h1{
padding:10px;
margin:20px;
font-size:40px;
text-transform:uppercase;
text-shadow:0px 0px 1px #fff;
color:#333;
background:transparent url(../images/line.png) repeat-x bottom left;
}
Для основной обертки слайдера (класс rm_wrapper
) установим следующие стилевые свойства:
.rm_wrapper{
width:1160px;
margin:0 auto;
position:relative;
}
Определим стиль для контейнера слайдера
.rm_container{
width:1050px;
overflow:hidden;
position:relative;
height:530px;
margin:0 auto;
}
Для заголовка контейнера стили будут следующие:
.rm_container h2{
background:transparent url(../images/lines.png);
padding:10px 30px;
position:absolute;
bottom:170px;
right:0px;
color:#000;
font-size:36px;
text-transform:uppercase;
text-shadow:1px 0px 1px #fff;
}
Ширину списка ul нужно установить большей, чем ширина контейнера, так как мы хотим, чтобы изображения следовали друг за другом.
.rm_container ul{
width:1170px;
}
Установив отрицательный левый отступ и толщину рамок списку элементов, мы перекрываем изображения и отрезаем правые границы, таким образом создаем нашу асимметричную форму изображений. Цвет рамок должен быть таким же, как и цвет фона контейнера.
.rm_container ul li{
float:left;
margin-left:-80px;
position:relative;
overflow:hidden;
width:310px;
height:465px;
border:30px solid #f0f0f0;
border-width:50px 30px 0px 30px;
background-color:#f0f0f0;
}
Изображениям придадим абсолютное позиционирование с помощью CSS свойства position:
.rm_container ul li img{
position:absolute;
top:0px;
left:0px;
}
Теперь напишем стили для масок и угловых элементов. Они абсолютно позиционируются и имеют серый фон. Поворачивая их, мы показываем изображение уже нужной формы.
.rm_mask_right, .rm_mask_left{
position: absolute;
height: 110px;
background: #f0f0f0;
width: 530px;
bottom: -30px;
left: 0px;
-moz-transform:rotate(-3deg);
-webkit-transform:rotate(-3deg);
transform:rotate(-3deg);
}
.rm_mask_right{
left:auto;
right:0px;
-moz-transform:rotate(3deg);
-webkit-transform:rotate(3deg);
transform:rotate(3deg);
}
.rm_corner_right, .rm_corner_left{
background: #f0f0f0;
position:absolute;
width:200px;
height:100px;
bottom:0px;
left:-65px;
-moz-transform:rotate(45deg);
-webkit-transform:rotate(45deg);
transform:rotate(45deg);
}
.rm_corner_right{
left:auto;
right:-65px;
-moz-transform:rotate(-45deg);
-webkit-transform:rotate(-45deg);
transform:rotate(-45deg);
}
Теперь расположим элементы управления слева и справа контейнера:
.rm_nav a{
position:absolute;
top:200px;
width:38px;
height:87px;
cursor:pointer;
opacity:0.7;
}
.rm_nav a:hover{
opacity:1.0;
}
.rm_nav a.rm_next{
background: url(../images/next.png) no-repeat;
right:0px;
}
.rm_nav a.rm_prev{
background: url(../images/prev.png) no-repeat;
left:0px;
}
Кнопку автоматического пролистывания изображений расположим сверху слайдера:
.rm_controls{
position:absolute;
top:0px;
left:-40px;
height:20px;
}
.rm_controls a{
cursor:pointer;
opacity:0.7;
padding-left:24px;
font-size:16px;
text-transform:uppercase;
height:20px;
float:left;
line-height:20px;
}
.rm_controls a:hover{
opacity:1.0;
}
.rm_controls a.rm_play{
display:none;
background:transparent url(../images/play.png) no-repeat center left;
}
.rm_controls a.rm_pause{
background:transparent url(../images/pause.png) no-repeat center left;
}
Итак, со стилями разобрались. Теперь давайте немного поскриптим. Принцип работы нашего слайдера заключается в добавлении нового изображение перед текущим со слегка увеличенным углом поворота. После этого, мы анимируем поворот и делаем изображение видимым. Начнем. Для начала «запомним» некоторые элементы и проверим используемый браузер, чтобы избежать проблем (ведь IE8 не умеет поворачивать элементы с помощью CSS3 стилей):
//Наши 4 видимые картинки
var $listItems = $('#rm_container > ul > li'),
totalItems = $listItems.length,
//Кнопки для управления слайдером
$rm_next = $('#rm_next'),
$rm_prev = $('#rm_prev'),
$rm_play = $('#rm_play'),
$rm_pause = $('#rm_pause'),
//Маски и углы для слайдера
$rm_mask_left = $('#rm_mask_left'),
$rm_mask_right = $('#rm_mask_right'),
$rm_corner_left = $('#rm_corner_left'),
$rm_corner_right= $('#rm_corner_right'),
//Проверка версии браузера <= IE8
ieLte8 = ($.browser.msie && parseInt($.browser.version) <= 8);
Если при использовании $.browser
у вас появилась ошибка TypeError: jQuery.browser is undefined
, тогда ознакомьтесь со статьей Замена $.browser в jQuery 1.9 и старше. Теперь давайте определим нашу функцию:
RotateImageMenu = (function() {
...
})();
RotateImageMenu.init();
И теперь давайте пропишем следующий код в нашей функции:
// Разница между анимациями изображений
var timeDiff = 300,
// Время между анимациями изображений (для слайдшоу)
slideshowTime = 3000,
slideshowInterval,
// Флаг, определяющий вращается ли изображение
isRotating = false,
// Счетчик изображений в итерации слайдшоу
completed = 0,
/*
Все изображения имеют ширину 310px и высоту 465px.
Если вы используете изображения разных размеров,
то эти величину нужно вычислять автоматически.
Мы устанавливаем вращение оригинала вокруг центра
с координатами x = ширина/2 и y = высота*2
*/
origin = ['155px', '930px'],
init = function() {
configure();
initEventsHandler();
},
// Инициализация некоторых событий
initEventsHandler = function() {
/*
При нажатии на кнопки со стрелками
останавливаем слайдшоу (stopSlideshow();)
и вращаем каждое изображение
(rotateImages(1), или rotateImages(-1), где
1 - поворот вправо, а -1 - поворот влево
*/
$rm_next.bind('click', function(e) {
stopSlideshow();
rotateImages(1);
return false;
});
$rm_prev.bind('click', function(e) {
stopSlideshow();
rotateImages(-1);
return false;
});
/*
Остановка и запуск слайдшоу
*/
$rm_play.bind('click', function(e) {
startSlideshow();
return false;
});
$rm_pause.bind('click', function(e) {
stopSlideshow();
return false;
});
/*
Добавляем события для мыши и кнопок влево/вправо
*/
$(document).bind('mousewheel', function(e, delta) {
if(delta > 0) {
stopSlideshow();
rotateImages(0);
}
else {
stopSlideshow();
rotateImages(1);
}
return false;
}).keydown(function(e){
/*
Определяем код кнопки и, если это кнопки влево\вправо,
то останавливаем слайдер и поворачиваем изображение
*/
switch(e.which){
case 37:
stopSlideshow();
rotateImages(0);
break;
case 39:
stopSlideshow();
rotateImages(1);
break;
}
});
},
/*
Функция для поворота изображений.
*/
rotateImages = function(dir) {
// Если анимация в процессе выполнения:
if(isRotating) return false;
isRotating = true;
$listItems.each(function(i) {
var $item = $(this),
/*
Вычисление задержки.
Если вращение выполняется вправо,
то первое изображение будет анимироваться первым,
иначе - последним
*/
interval = (dir === 1) ? i * timeDiff : (totalItems - 1 - i) * timeDiff;
setTimeout(function() {
// Изображения, связанные с данным блоком
var $otherImages = $('#' + $item.data('images')).children('img'),
totalOtherImages = $otherImages.length;
// Текущее изображение
$img = $item.children('img:last'),
// Отслеживать для каждого пункта текущее изображение
current = $item.data('current');
// Проверяем выход за пределы списка
if(current > totalOtherImages - 1)
current = 0;
else if(current < 0)
current = totalOtherImages - 1;
// Следующее изображение для вывода и его
// начальное вращение (зависит от направления)
var otherRotation = (dir === 1) ? '-30deg' : '30deg',
$other = $otherImages.eq(current).clone();
// Для IE <= 8 поворота изображения не будет,
// но будет затухание ... Лучше, чем ничего :)
if(!ieLte8)
$other.css({
rotate : otherRotation,
origin : origin
});
(dir === 1) ? ++current : --current;
// Вставляем следующее изображение для <li>
$item.data('current', current).prepend($other);
// Окончательное вращение для текущего изображения
var rotateTo = (dir === 1) ? '80deg' : '-80deg';
if(!ieLte8) {
$img.animate({
rotate : rotateTo
}, 1200, function(){
$(this).remove();
++completed;
if(completed === 4) {
completed = 0;
isRotating = false;
}
});
$other.animate({
rotate : '0deg'
}, 600);
}
else {
$img.fadeOut(1200, function(){
$(this).remove();
++completed;
if(completed === 4) {
completed = 0;
isRotating = false;
}
});
}
}, interval );
});
},
// Устанавливаем начальное вращение
configure = function() {
if($.browser.msie && !ieLte8)
rotateMaskCorners();
else if(ieLte8)
hideMaskCorners();
$listItems.each(function(i) {
// Начальное значение current равно 1,
// так как мы уже показали первое изображение
var $item = $(this).data('current', 1);
if(!ieLte8)
$item.transform({rotate: $item.data('rotation') + 'deg'})
.find('img')
.transform({origin: origin});
});
},
// Вращаем маски и углы
rotateMaskCorners = function() {
$rm_mask_left.transform({rotate: '-3deg'});
$rm_mask_right.transform({rotate: '3deg'});
$rm_corner_left.transform({rotate: '45deg'});
$rm_corner_right.transform({rotate: '-45deg'});
},
// Скрываем маски и углы
hideMaskCorners = function() {
$rm_mask_left.hide();
$rm_mask_right.hide();
$rm_corner_left.hide();
$rm_corner_right.hide();
},
startSlideshow = function() {
clearInterval(slideshowInterval);
rotateImages(1);
slideshowInterval = setInterval(function() {
rotateImages(1);
}, slideshowTime);
// Выводим кнопку паузы и скрываем кнопку запуска слайдера
$rm_play.hide();
$rm_pause.show();
},
stopSlideshow = function() {
clearInterval(slideshowInterval);
// Выводим кнопку запуска слайдера и скрываем кнопку с паузой
$rm_pause.hide();
$rm_play.show();
};
return {init : init};
Вот и все, мы славно потрудились и теперь наш слайдер с вращающимися изображениями может быть использован на Вашем сайте.