Добрый день, уважаемые читатели!

Наконец-то выпала свободная минута и по Вашим просьбам я написал еще один, маленький скрипт для не циклического слайдера. В принципе ничего сложного, но при разработке возникла пара интересных моментов %). Кстати Вы можете почитать как сделать циклический слайдер с горизонтальной прокруткой или как сделать простой слайдер на миниатюрах.

Простой слайдер с горизонтальной прокруткой (не циклический)

Чтобы увидеть скрипт слайдера в действии — кликните по кнопочке «Demo» и конечно же можете скачать пример урока кликнув по кнопке «Source»:

Итак, длинное вступление я пропущу и перейду сразу к делу:

Строим HTML каркас слайдера

Разметка слайдера будет такая же как и в предыдущем уроке:

<div class="slider">
  <div class="slide-list">
    <div class="slide-wrap">
		
      <!-- Список слайдов -->
	  
      <div class="slide-item">
        <div class="slide-thumb"><img src="img/img-1.jpg" alt="" /></div>
        <span class="slide-title">
          <a href="#" target="_blank">Календула – цветок красоты и здоровья</a>
        </span>
      </div>

      <div class="slide-item">
        <div class="slide-thumb"><img src="img/img-2.jpg" alt="" /></div>
        <span class="slide-title">
          <a href="#" target="_blank">Тысячелистник обыкновенный — Achilea millefolium</a>
        </span>
      </div>
	  
      ...... Здесь остальные слайды

    </div>
  </div>
	
  <a href="#" class="navy prev-slide disabled"><i class="icon-left-open-big"></i></a>
  <a href="#" class="navy next-slide"><i class="icon-right-open-big"></i></a>

</div>

Чуток описания разметки слайдера:

  • .slider — контейнер слайдера,
  • .slider-list — видимая часть слайдера,
  • .slider-wrap — обертка слайдов,
  • .slide-thumb — контейнер миниатюры слайда,
  • .slide-title — контейнер для названия слайда,
  • .navy — навигация слайдера, в примере я использую шрифт-иконки от сервиса Fontello, очень просто и удобно, советую Вам попробовать (работает и в ие7, но стили для него в этом примере я не писал),
  • .navy.disabled — заблокированная навигационная ссылка.

С разметкой разобрались, теперь дело за каскадными таблицами стилей

Стилизируем слайдер

Я пишу стилей по минимуму (как обычно), ну а Ваша фантазия может здесь себя проявить:

/* Slider */
.slider {
  /* Ширина контейнера */
  width: 900px;
  /* Внешние тступы сверху и снизу */
  margin: 50px auto;
  /* Внутренние отступы для ссылок navy */
  padding: 0 50px;
  /* Позиционирование, нужно для навигации вперед/назад */
  position: relative;
}
.slide-list {
  /* Показываем только то что нужно */
  overflow: hidden;
  /* Позиционирование */
  position: relative;
}
.slide-wrap {
  /* Позиционирование */
  position: relative;
  /* Ширина обертки */
  width: 10000px;
  /* Сбрасываем обтекание */
  clear: right;
}
.slide-item {
  /* Ширина слайда */
  width: 280px;
  /* Внутренние отступы */
  padding: 10px;
  /* Обтекание */
  float: left;
}
.slide-thumb {
  /* Высота бокса миниатюры */
  height: 200px;
  /* Высота строки бокса миниатюры */
  line-height: 200px;
  /* В моем примере картинки разного размера, поэтому я указал высоту и бокса и скрываю то что за него выходит */
  overflow: hidden;
}
.slide-thumb img {
  /* Ширина картинки */
  width: 100%;
  /* Вертикальное выравнивание миниатюры */
  display: inline;
  vertical-align: bottom;
}
.slide-title a {
  /* Стилизация ссылок названия слайда */
  color: #6b2525;
  font-size: 16px;
  font-weight: bold;
  font-family: monospace;
  line-height: 1.3;
  display: block;
  padding-top: 10px;
  text-shadow: 0 1px white;
}
.slide-title a i {
  /* Стилизация иконки названия слайда */
  font-size: 12px;
  color: #666;
}

/* навигация по слайдеру */
.navy {
  /* абсолютное позиционирование */
  position: absolute;
  top: 80px;
  /* размеры ссылок */
  width: 50px;
  height: 50px;
  /* положение, цвет, размер шрифта */
  color: #0074A3;
  text-align: center;
  line-height: 50px;
  font-size: 3em;
  font-weight: bold;
  text-shadow: 0 1px #fff;
  /* анимация CSS3*/
  transition: all .5s;
  -o-transition: all .5s;
  -moz-transition: all .5s;
  -webkit-transition: all .5s;
}
/* позиционирование навигационных сссылок */
.prev-slide {
  left: 0px;
}
.next-slide {
  right: 0px;
}
/* событие наведения на стрелку */
.navy:hover {
  color: #073e61;
}
/* событие клика на стрелку */
.navy:active {
  top: 82px;
  color: #ed0000;
}
/* заблокированная навигационная ссылка */
.navy.disabled,
.navy.disabled:hover,
.navy.disabled:active {
  opacity: 0;
  filter: alpha(opacity=0);
  cursor: default;
}

В приведенных стилях есть комментарии, в них я указал всякие стилизационные штучки))

Наконец-то мы подошли к самому инетересному моменту этого урока.

Пишем скрипт слайдера

Создаем файл slider.js и вносим в него стартовую информацию:

jQuery(document).ready(function(){
  function htmSliderNotloop(){
    
	тут будет скрипт
	...
	
  }
  /* иницилизируем функцию слайдера */
  htmSliderNotloop();
});

Следующим шагом зададим переменные, которыми будем пользоваться:

/* Зададим следующие переменные */
var viewSliderNum = 3,
    animDuration = 1000,
    slideWrap = jQuery('.slide-wrap'),
    nextLink = jQuery('.next-slide'),
    prevLink = jQuery('.prev-slide'),
    slideNum = slideWrap.find('.slide-item').size(),
    slideWidth = jQuery('.slide-item').outerWidth(),			
    sliderEndPoint = (slideNum - viewSliderNum)*slideWidth*(-1);

Подробнее о заданных переменных:

  • viewSliderNum — количество отображаемых слайдов,
  • animDuration — скорость анимации слайдера в милисекундах,
  • slideWrap — обертка списка слайдов,
  • nextLink — ссылка на следующий слайд,
  • prevLink — ссылка на предыдущий слайд,
  • slideNum — количество слайдов,
  • slideWidth — ширина слайда,
  • sliderEndPoint — максимальная позиция куда может доехать обертка слайдера (умножаем на -1, потому что двигаемся влево, причем, в отрицательном направлении).

Опишем события кликов по ссылкам вперед/назад:

/* Клик по ссылке на следующий слайд */
nextLink.click(function(){
  if(jQuery(this).hasClass('disabled')){
    return false
  } else {
    if(!slideWrap.is(':animated')) {

      var leftSlidePos = slideWrap.position().left,
          lsp = Math.round(leftSlidePos/100)*100,
          newLeftPos = lsp - slideWidth,
          nlp = Math.round(newLeftPos/100)*100;

      slideWrap.animate({left: nlp}, animDuration, function(){

        slideWrap.css({'left':nlp});

        if(nlp == sliderEndPoint){
          nextLink.addClass('disabled');
        }
        if(nlp != sliderEndPoint) {
          nextLink.removeClass('disabled');
        }
        if(nlp == 0){
          prevLink.addClass('disabled');
        }
        if(nlp != 0){
          prevLink.removeClass('disabled');
        }

      });

    }
  }
  return false
});

/* Клик по ссылке на предыдующий слайд */
prevLink.click(function(){
  if(jQuery(this).hasClass('disabled')){
    return false
  } else {
    if(!slideWrap.is(':animated')) {

      var leftSlidePos = slideWrap.position().left,
          lsp = Math.round(leftSlidePos/100)*100,
          newLeftPos = lsp + slideWidth,
          nlp = Math.round(newLeftPos/100)*100;

      slideWrap.animate({left: nlp}, animDuration, function(){

        slideWrap.css({'left':nlp});

        if(nlp == sliderEndPoint){
          nextLink.addClass('disabled');
        }
        if(nlp != sliderEndPoint) {
          nextLink.removeClass('disabled');
        }
        if(nlp == 0){
          prevLink.addClass('disabled');
        }
        if(nlp != 0){
          prevLink.removeClass('disabled');
        }
      });

    }
  }
  return false		
});

Пришло время для детального описания кликов:

Произошел клик по ссылке, первым делом проверяем наличие класса disabled у ссылки, если он есть, то ниче не происходит (в принципе ссылка и так скрыта от глаз пользователя, но мало ли что%).

Дальше идет проверка на анимацию слайдера, то есть если слайдер уже движется, то ниче не происходит (тут большое спасибо Игорю за подсказку), а если же нету то выполняется наш расчет.

А наш расчет такой: находим текущую левую позицию обертки слайдера, округляем ее до целых числел, чтобы было два нуля в конце(почему так напишу ниже) далее, для ссылки вперед отнимаем от этой позиции ширину слайда (для ссылки назад — прибавляем ширину слайда) и полученное число также округляем до целых цисел чтобы было два нуля в конце числа.

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

Но, помните мы округляли числа, зачем это было нужно? Вроде бы и без округлений все понятно. Так то оно так, но сначала у меня было 5 слайдов и все работало замечательно и без округления, потом я добавил 10 слайдов и кнопки перестали блокироваться. Причина была в том что Google Chrome (а может и другие браузеры) после 8-го слайда стал рассчитывать левую позицию обертки, не точно, а со знаками после запятой, причем округление до обычного целого числа не помогло, а так как у меня слайды по ширине 300 пикселей то и округлял я целое число так, чтобы оставалось два нуля в конце, если у Вас слайды будут другой ширины, то возможно Вам пригодится эта тема про округление чисел на форуме javascript, хорошо что методы округления есть разные)

Приведу полный листинг файла slider.js, чтобы не было путаницы:

jQuery(document).ready(function(){
  function htmSliderNotloop(){

    /* Зададим следующие переменные */
    var viewSliderNum = 3,
        animDuration = 1000,
        slideWrap = jQuery('.slide-wrap'),
        nextLink = jQuery('.next-slide'),
        prevLink = jQuery('.prev-slide'),
        slideNum = slideWrap.find('.slide-item').size(),
        slideWidth = jQuery('.slide-item').outerWidth(),			
        sliderEndPoint = (slideNum - viewSliderNum)*slideWidth*(-1);

    /* Клик по ссылке на следующий слайд */
    nextLink.click(function(){
      if(jQuery(this).hasClass('disabled')){
        return false
      } else {
        if(!slideWrap.is(':animated')) {

          var leftSlidePos = slideWrap.position().left,
              lsp = Math.round(leftSlidePos/100)*100,
              newLeftPos = lsp - slideWidth,
              nlp = Math.round(newLeftPos/100)*100;

          slideWrap.animate({left: nlp}, animDuration, function(){

            slideWrap.css({'left':nlp});

            if(nlp == sliderEndPoint){
              nextLink.addClass('disabled');
            }
            if(nlp != sliderEndPoint) {
              nextLink.removeClass('disabled');
            }
            if(nlp == 0){
              prevLink.addClass('disabled');
            }
            if(nlp != 0){
              prevLink.removeClass('disabled');
            }
          });
        }
      }
      return false
    });

    /* Клик по ссылке на предыдующий слайд */
    prevLink.click(function(){

      if(jQuery(this).hasClass('disabled')){
        return false
      } else {
        if(!slideWrap.is(':animated')) {

          var leftSlidePos = slideWrap.position().left,
              lsp = Math.round(leftSlidePos/100)*100,
              newLeftPos = lsp + slideWidth,
              nlp = Math.round(newLeftPos/100)*100;

          slideWrap.animate({left: nlp}, animDuration, function(){

            slideWrap.css({'left':nlp});

            if(nlp == sliderEndPoint){
              nextLink.addClass('disabled');
            }
            if(nlp != sliderEndPoint) {
              nextLink.removeClass('disabled');
            }
            if(nlp == 0){
              prevLink.addClass('disabled');
            }
            if(nlp != 0){
              prevLink.removeClass('disabled');
            }
          });
        }
      }
      return false		
    });

  }

  /* иницилизируем функцию слайдера */
  htmSliderNotloop();
  
});

Заключение:

Благодаря простоте jQuery мы теперь умеем делать три типа слайдеров: циклический, не циклический и на миниатюрах. В скором времени я, надеюсь, напишу еще один слайдер, который объединит слайдер на миниатюрах с нециклическим слайдером. Ну и конечно же вопросы и пожелания оставляйте в коментариях.

Всем удачи!

Добавить комментарий:


Комментарии
  1. oleg

    попробовал поставить себе на сайт. не работает прокрутка .. в консоль лог пишет было 0 стало 0 . при повторном заходе не страницу начинает работать. не пойму в чем причина.

  2. JAH

    Олег, а какая версия jQuery? какие еще скрипты используете на сайте? можно ссылку на сайт?

  3. Денис

    JAH, в первую очередь, большое спасибо за слайдер!
    Вот захотел я сделать прокрутку контента, и вспомнил про Ваш блог, где есть отличный слайдер).
    Так вот что мне нужно, что бы слайдер прокручивался вертикально, а не горизонтально (в скрипте не нашел, где изменить ориентацию). Так же нужно прокручивать, не картинки, а скажем текст абзацами, ну думаю это не проблема, запихнуть место картинок текст. В общем буду очень благодарен, если подскажите как изменить ориентацию на вертикальную.
    p.s. Так же при клике «Вверх» и «Вниз», желательно что бы плавно прокручивался контент, на определенное расстояние, а не как в Вашем примере слайдера блоками (картинками).
    Это

    overflow:auto

    , использовать не хочу, хочу именно слайдер, что бы было две кнопки (ссылки), вверх и вниз. (вот такое вот извращение) 🙂