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

Разметка 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%;
}

Ширина изображения будет установлена в нашем javascript, но мы всё равно определим её, на случай выключенного 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;
    }
}

Для случаев, когда javascript выключен, мы добавим этот кусочек CSS, для гарантии того, что слайды будут показаны. Навигация с миниатюрами будет скрыта:

.ei-slider{
    height: auto;
}
.ei-slider-thumbs{
    display: none;
}
.ei-slider-large li{
    position: relative;
}

Вот и  всё со стилями, перейдем к javascript.

javascript

В начале подключаем, как обычно, jQuery, наш плагин (о нём подробнее речь пойдет ниже), плагин easing эффектов и инициализация нашего плагина с настройками:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.eislideshow.js"></script>
<script type="text/javascript" src="js/jquery.easing.1.3.js"></script>
<script type="text/javascript">
    $(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;
    
    });
    
}
};

Вот и всё.

СКАЧАТЬСкачек: 1164
413,85 Kb
Кто скачал?

ДЕМОПосмотреть
пример