3 187 Скрипты / Slider

Слайдшоу с предпросмотром


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

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;
  });
}
};

Вот и всё.

Скачать 1384Загрузок 413,85 Kb
Демо

Комментарии

  • Facebook
  • Вконтакте

Похожие статьи