Lecaw

Учимся создавать Web-сайты

Как сделать горизонтальный jQuery слайдер для сайта с эффектом перелистывания картинок

October 3, 2012 1211hits

В последнее время, на многих веб-сайтах стали использовать эффект 'перелистывания страниц', поэтому я начал размышлять о том, как создать горизонтальный jQuery слайдер с эффектом перелистывания картинок. Я попытался сделать создание эффекта максимально простым.

ДЕМО Исходные файлы

 

Что нам нужно для создания jQuery слайдера

  • Нам нужен контейнер с изображениями, которые преобразуем в книгу
  • Нам нужны стрелки и круговые кнопки, чтобы показать пользователю, на какой странице они находятся
  • Страницы должны быть представлены как изображения в HTML и должны быть разделены (каждое изображение становится двумя блоками)
  • Нам нужно реализовать большую часть интерфейса при помощи jQuery
  • jQuery слайдер должен работать во всех современных браузерах

Подключаем файлы

Так как мы будем создавать jQuery слайдер, нам нужно подключить jQuery сценарии к основной странице. Затем, подключим дополнительный сценарий – Modernizr, можете загрузить его отсюда. Этот сценарий нужен для правильной работы jQuery слайдера, в браузерах, которые не поддерживают CSS transforms. Затем подключим файлы - jquery.pictureflip.js, в нем будет содержаться код плагина!

<script src="/modernizr.js"></script>
<script src="/jquery.js"></script>
<script src="/javascript.js"></script>

Основной код jQuery слайдера

Основной HTML код довольно прост. Я буду использовать контейнер, чтобы была возможность расположить jQuery слайдер в любом месте сайта. Все что нужно сделать это – поместить каждое изображение в отдельный блок и задать уникальный ID.

<div id="container">
<div id="flipbook">

<div id="image-1"> <div class="content"><a href="#">Flowers: What you didn't know</a></div> </div>
<div id="image-2"> <div class="content"><a href="#">Flowers: Real or Fiction?</a></div> </div>
<div id="image-3"> <div class="content"><a href="#">A Flower ate my Baby!</a></div> </div>
<div id="image-4"> <div class="content"><a href="#">Will Flowers Destroy Earth?</a></div> </div>


</div>
</div>

Прежде чем мы перейдем к jQuery, добавим CSS transforms.

CSS

Вместе c простыми свойствами CSS, мы будем использовать 3D transforms, чтобы создать эффект зеркального отражения страницы. Затем в jQuery разделим изображения на два блока и повернем один блок таким образом, как будто это зеркальное отражение. Для начала добавим основной код CSS.

#container {
    padding: 10px;
    box-shadow: 0px 0px 10px rgba(0,0,0,0.1);
    margin: 20px auto;
    width: 600px;
    height: 330px;
}
 
.flipbook {
    position: relative; 
    width: 600px;
    height: 300px;
    z-index: 999;
}
 
.flipbook > div {
    width: inherit;
    height: inherit;
    position: absolute;
    top: 0px;
    left: 0px;
    text-align: left;
}
 
.flipbook .hide {
    display: none;
}
 
.flipbook > div > div {
    width: inherit;
    height: inherit;
    background-size: 600px 300px;
    width: 50%;
    height: 100%;
    position: absolute;
}
 
/* Разделим изображения на два блока. */
/* Один – справа, второй - слева */
.flipbook div[class$="-fend"] {
    background-position: 100% 0;
    left: 50%;
}

Основная часть jQuery кода, передвигает две фигуры, двух изображений при помощи вызова определенной функции. Поэтому нам надо правильно расположить эти блоки (вплотную) и повернем их, что бы добавить эффект вращения. Затем поместим их обратно в контейнеры с изображениями. Для правильной работы, мы должны сохранить 3D эффект в CSS, таким образом, чтобы мы могли применить его в различных элементах.

/* Сохранение 3D */
 
.flipbook .moving-div {
    z-index: 99999;
    width: 50%;
     
    -webkit-perspective: 1000;
    -webkit-transform-style: preserve-3d;
    -webkit-transform-origin: 0 0;
     
    -moz-perspective: 1000;
    -moz-transform-style: preserve-3d;
    -moz-transform-origin: 0 0;
 
    -o-perspective: 1000;
    -o-transform-style: preserve-3d;
    -o-transform-origin: 0 0;
     
    -ms-perspective: 1000;
    -ms-transform-style: preserve-3d;
    -ms-transform-origin: 0 0;
     
    perspective: 1000;
    transform-style: preserve-3d;
    transform-origin: 0 0;
}
 
/* Задние стороны будут невидимыми */
.flipbook .moving-div div {
    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    -o-backface-visibility: hidden;
    -ms-backface-visibility: hidden;
    backface-visibility: hidden;
    width: 100%;
    z-index: 9999;
}
/* Удостоверьтесь что правильно расположили все блоки */
.flipbook .moving-div > div[class$="-fend"] {
    left: 0;
}
 
/* Повернем первый блок вплотную ко второму */
.flipbook .moving-div > div[class$="-fstart"] {
    -webkit-transform: rotateY(180deg);
    -moz-transform: rotateY(180deg);
    -o-transform: rotateY(180deg);
    -ms-transform: rotateY(180deg);
    transform: rotateY(180deg);
}

Есть также два блока используемые как тени, которые придают ощущение глубины при перелистывании страницы jQuery слайдера.

/* Два блока с тенью */
.flipbook .moving-div span {
    box-shadow: inset 60px 0 60px -60px rgba(0,0,0,0.1);
    width: 100%;
    height: 100%;
    position: absolute;
    opacity: 0;
    display: block;
    z-index: 999999;
    top: 0; 
    background: rgba(0,0,0,0.1);
    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    -o-backface-visibility: hidden;
    -ms-backface-visibility: hidden;
    backface-visibility: hidden;
    left: 0;
}
 
.flipbook .moving-div span:last-of-type {
    -webkit-transform: rotateY(180deg); 
    -moz-transform: rotateY(180deg);
    -o-transform: rotateY(180deg);  
    -ms-transform: rotateY(180deg); 
    transform: rotateY(180deg); 
    box-shadow: inset -60px 0 60px -60px rgba(0,0,0,0.1);
}

Есть также несколько других классов для фактического вращения нашего блока. Они используют простые 3D transforms.

.flipbook .rotateYForward {
    -webkit-transform: rotateY(180deg); 
    -webkit-transition: -webkit-transform 1s ease-in;
     
    -moz-transform: rotateY(180deg);    
    -moz-transition: -moz-transform 1s ease-in;
     
    -o-transform: rotateY(180deg);  
    -o-transition: -o-transform 1s ease-in;
     
    -ms-transform: rotateY(180deg); 
    -ms-transition: -o-transform 1s ease-in;
     
    transform: rotateY(180deg); 
    transition: transform 1s ease-in;
    left: 50%;
}
 
.flipbook .beginMove {
    left: 50%;
    -webkit-transform: rotateY(180deg);
    -moz-transform: rotateY(180deg);    
    -o-transform: rotateY(180deg);  
    transform: rotateY(180deg); 
}
 
.flipbook .rotateYBackward {
    -webkit-transform: rotateY(360deg);
    -webkit-transition: -webkit-transform 1s ease-in;
     
    -moz-transform: rotateY(360deg);
    -moz-transition: -moz-transform 1s ease-in;
     
    -o-transform: rotateY(360deg);
    -o-transition: -o-transform 1s ease-in;
     
    -ms-transform: rotateY(360deg);
    -ms-transition: -o-transform 1s ease-in;
     
    transform: rotateY(360deg);
    transition: transform 1s ease-in;
}

Следующий этап прост, мы разработаем стрелки навигации, а также небольшие круги, которые показывают номер текущего слайда.

.flipbook .back-arrow, .flipbook .forward-arrow {
    width: 100px;
    height: 100px;
    box-sizing: border-box;
        -moz-box-sizing: border-box;
    padding: 8px 28px;
    font-size: 7em;
    font-weight: bold;
    z-index: 10;
    left: -140px;
    color: #fff;
    top: 30%;
    border-radius: 100px;
    position: absolute;
    cursor: pointer;
    z-index: 999999;
    background-color: #396275;
}
 
.flipbook div[class$="-arrow"]:hover {
    box-shadow: inset 0px 0px 30px rgba(0,0,0,0.2);
}
 
.flipbook div[class$="-arrow"]:active {
    background-color: #2e505f;
    box-shadow: inset 0px 0px 30px rgba(0,0,0,0.1);
}
 
.flipbook .forward-arrow {
    right: -140px;
    left: auto;
    padding: 8px 34px;
    font-weight: bold;
}
 
.flipbook .buttons {
    width: 98%;
    padding: 7px 1%;
    height: 16px;
    background: #fff;
    position: relative;
    top: 300px;
     
}
 
.flipbook .buttons span {
    background: #fff;
    box-shadow: inset 0 0 8px rgba(0,0,0,0.1);
    width: 16px;
    cursor: pointer;
    height: 16px;
    border-radius: 16px;
    display: block;
    float: right;
    position: relative;
    margin-right: 5px;
}
 
.flipbook .buttons .selected {
    background-color: #47b1e2;
    box-shadow: inset 0 0 10px rgba(0,0,0,0.1);
}
 
.flipbook .content {
    display: none;
    height: 30px;
    padding: 7px;
    z-index: 99999999;  
    position: absolute;
    bottom: 0;
    width: 50%;
    font-size: 2em;
}
 
.flipbook a {
    color: #fff;
    font-weight: bold;
    text-decoration: none;
    border-bottom: 2px solid #fff;
    text-shadow: 0 0 10px rgba(0,0,0,0.1);
}

Мы переходим к этапу добавления изображений. Я решил использовать 4 изображения, но вы можете добавить больше. Они будут размещены в контейнерах с изображениями, которые мы определили ранее в HTML.

/* Используемые изображения */
div[class^="image-1-"] {
    background: url('images/1.jpg');
}
 
div[class^="image-2-"] {
    background: url('images/2.jpg');
}
 
div[class^="image-3-"] {
    background: url('images/3.jpg');
}
 
div[class^="image-4-"] {
    background: url('images/4.jpg');
}

jQuery плагин

Откройте файл jquery.pictureflip.js. Базовая структура jQuery слайдера:

(function($){
 
    $.fn.extend({ 
         
        // Имя плагина  
        pictureflip: function(options) {
             
            // Значения по умолчанию
            var defaults = {
                time: 1000,
                start: 1
            }
         
            // Подключение значений с функциональными переменными
            var options = $.extend(defaults, options);
              
             
            // Мы должны вызвать каждый объект, к которому применяется плагин
            // Вы можете добавить больше функций в конце плагина, т.е.
            // $('#item').pictureflip().appendClass('pictures');
             
            return this.each(function() {
             
                var o = options;
                var obj = $(this);
                    
            });
 
        }
     
    });
     
})(jQuery);

Для начала установим основные переменные, такие как - число изображений и проверка анимации, чтобы проверить, анимируются ли изображения.

var time = o.time;
var imageNumber = $('div[id^="image"]', obj).length;
var animated = 0;

В следующем шаге добавим UI.

// Добавление UI
obj.append('<div class="back-arrow"><</div><div class="forward-arrow">></div><div class="moving-div hide"><span></span><span></span></div><div class="buttons"></div>'); obj.addClass('flipbook');

// Добавление круговых кнопок
while(imageNumber > 0) {
$('<span class="button-'+imageNumber+'"></span>').appendTo($('.buttons'));
--imageNumber;
}

// Добавление контента
$('div[id^="image-"]:first .content', obj).fadeIn();

// Добавление функции
selectCircle();

Затем мы должны определить несколько простых функций. Эти функции касаются анимаций, z-index и перезапуска jQuery слайдера.

// Изменение z index 
function zIndexFix() {
         
    $('[id^="image"]').each(function(index) {
        zindex = index * -1;
        $(this).css('zIndex', zindex);
    });
             
}
             
// Перезапуск слайдов, для зеркального отображения
function restartSlides() {
                 
    var $moveFirst = $('.moving-div div:first').attr('class').split('-')[1];
    var $moveLast = $('.moving-div div:last').attr('class').split('-')[1];
             
    $('> .moving-div div:first', obj).appendTo($('> #image-'+$moveFirst, obj));
    $('> .moving-div div:last', obj).appendTo($('> #image-'+$moveLast, obj));
                 
    $('.moving-div').removeClass('rotateYForward rotateYBackward beginMove').removeAttr('style');
                 
    $('.moving-div').addClass('hide');
}
     
    // Анимация тени 
function shadowAnimate(time) {
                 
    $('.moving-div span').animate({opacity : 1}, time/2);
                 
    setTimeout(function() {
                     
        $('.moving-div span').animate({opacity : 0}, time/2);
                 
    }, time/2);
             
}
             
// Отметка изображений
function selectCircle() {
    var imageID = parseFloat($('> div[id^="image"]:first', obj).attr('id').split('-')[1]);
                 
    $('.buttons span').removeClass('selected');
    $('.buttons .button-'+imageID).addClass('selected');
                 
}

Теперь мы можем построить функцию анимации кнопок! Мы могли бы сделать две анимации (одна для кнопки "Назад" и а вторая для кнопки "Вперед"), но вместо этого я решил сделать одну анимацию для двух кнопок. Я добавил переменную, которая проверит тип кнопки (вперед или назад) и после этого скорректирует jQuery код. Предыдущая переменная, просто проверяет, какую кнопку нажимает пользователь! Кнопки не работают в браузере Safari, я отключил эффект зеркального отражения в Safari.

// функция анимации
function animation(prev, time, buttons) {
                 
    // Постепенное исчезновение контента
    $('div[id^="image-"]:first .content', obj).fadeOut(50);
                 
    // Если не работает анимация
    if(animated == 0) {
        // Запуск анимации
        animated = 1;
                             
            // Следующий слайд который будет показан
            if(prev != true) {
                var $nextSlide = $('div[id^="image-"]:first ~ div[id^="image-"]:first', obj).attr('id');
            } else {
                var $nextSlide = $('div[id^="image-"]:last', obj).attr('id');
            }
                         
            // Текущий слайд
            var $thisSlide = $('div[id^="image-"]:first', obj).attr('id');
                                                    
            if(Modernizr.csstransforms3d == "" || (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1)) {
                                 
                $('> #'+$nextSlide, obj).prependTo(obj);
                if(prev != true) {
                    $('> #'+$thisSlide, obj).appendTo(obj);
                }
                animated = 0;
                zIndexFix();
                selectCircle();
                                 
                return false;
                             
            }
                         
            // Если это кнопка Вперед
            if(prev != true) {
                             
                // Добавление движущихся блоков
                $('> #'+$nextSlide+' > div[class$="-fstart"], > #'+$thisSlide+' > div[class$="-fend"]', obj).appendTo($('.moving-div'));
                             
                             
                // Поворот движущихся блоков и изменение времени поворота
                $('.moving-div', obj).addClass('rotateYForward').css({
                             
                    '-webkit-transition-duration': time/1000+'s',
                    '-moz-transition-duration': time/1000+'s',
                    '-ms-transition-duration': time/1000+'s',
                    '-o-transition-duration': time/1000+'s',
                    'transition-duration': time/1000+'s'
                     
                });
                                 
                // Переместим блоки так, чтобы следующий блок был в верхней части,
                // а последний блок в нижней
                $('> #'+$nextSlide, obj).prependTo(obj);
                $('> #'+$thisSlide, obj).appendTo(obj);
                                 
            }
            else {
                // Если это кнопка Назад
                $('> #'+$thisSlide, obj).prependTo($(obj));
                $('> #'+$nextSlide, obj).insertAfter($('div[id^="image-"]:first', obj));
                             
                // Добавление движущихся блоков
                $('> #'+$nextSlide+' > div[class$="-fend"], > #'+$thisSlide+' > div[class$="-fstart"]', obj).appendTo($('.moving-div'));
                             
                // Фиксируемый z-index  
                zIndexFix();
                         
                // Поворот движущихся блоков
                $('.moving-div').addClass('beginMove');
                             
                // Настройка тайм-аута  в начале анимации
                setTimeout(function() {
                                 
                    // Поворот
                    $('.moving-div').addClass('rotateYBackward').css({
                                 
                        '-webkit-transition-duration': time/1000+'s',
                        '-moz-transition-duration': time/1000+'s',
                        '-ms-transition-duration': time/1000+'s',
                        '-o-transition-duration': time/1000+'s',
                        'transition-duration': time/1000+'s'
                                     
                    });
                                 
                }, time/50);
                                 
            }
                         
            // Анимация тени
            shadowAnimate(time);
                         
            // Настройка тайм-аута в конце анимации
            setTimeout(function() {
                        restartSlides();
                             
                if(buttons != true) {
                    $('.moving-div').addClass('hide');
                }
                             
                if(prev == true) {
                    $(' > #'+$nextSlide, obj).prependTo($(obj));
                }
                             
                // Изменение круга
                zIndexFix();
                selectCircle();
                             
               animated = 0;
                             
                // Постепенно отображаем контент
                $('div[id^="image-"]:first .content', obj).fadeIn();
                             
                             
            }, time);
                                 
        }
                     
         
}

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

$('.forward-arrow').click(function() {
    $('.moving-div').removeClass('hide');
    setTimeout(function() {
        animation(false, time);
    }, 1);
});
             
$('.back-arrow').click(function() { 
    $('.moving-div').removeClass('hide');
    setTimeout(function() {
        animation(true, time);
    }, 1);
});

Следующий шаг - небольшие круговые кнопки в нижней части. Нам нужно проверить ,что количество кнопок было равно количеству изображений. Чтобы сделать это, мы используем setInterval, который выполнит код несколько раз в определенном интервале.

// При нажатии кнопки
$('.buttons span[class^="button-"]', obj).click(function() {    
                 
    // Удаление класса из движущегося блока
    $('.moving-div').removeClass('hide');
             
    // Получение ID кнопки
    var buttonID = parseFloat($(this).attr('class').split('-')[1]);
                 
    // Получение ID текущего изображения 
    var currentImageID = parseFloat($('> div[id^="image"]:first', obj).attr('id').split('-')[1]);
                 
    var reduxTime = time/10;    
                 
    // Набор переменных с использованием функции rotateImages 
    var interval = setInterval(rotateImages, reduxTime);
                 
             
    function rotateImages() {
                     
        // Обновление текущей переменной 
        currentImageID = parseFloat($('> div[id^="image"]:first', obj).attr('id').split('-')[1]);
                     
        // Если ID кнопки равен ID изображения
        if(buttonID == currentImageID) {
            // Анимация закончена, очистка интервала
            clearInterval(interval);
            $('.moving-div').addClass('hide');
            // Завершение функции
            return false;
        }
        else {
            // В противном случае продолжим выполнение анимации
            animation(false, reduxTime, true);
        }               
                     
    }
         
});

Все что осталось сделать, это убедится, что установлен правильный z-index.

// Удостоверьтесь что зафиксировали z-index
zIndexFix();
             
// И изменение стартового изображения, выбранное пользователем
$('.buttons .button-'+o.start, obj).click();

Запуск jQuery слайдера

Для работы мы установили две опции, время (длительность анимации перелистывания) и стартовое изображение. Они не должны быть определены (значения по умолчанию составляют 1000 мс и запускается первое изображение). Чтобы запустить плагин, просто добавьте это к заголовку документа:

<script type="text/javascript">
$(document).ready(function() {

$('#flipbook').pictureflip({time : 1000, start : 1});

});
</script>

ДЕМО Исходные файлы

 

Дополнительная информация

Влерий Аликин - веб-разработчик & дизайнер. Соучредитель и член команды Lecaw.

Эл. почта
RATTING:
(0 голосов)

Оставить комментарий