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

Баннер должен удовлетворять таким требованиям:

1. Баннер представляет собой несколько изображений, они автоматически перелистываются спустя некоторый интервал времени. В нашем примере баннеров 5.
2. Каждая картинка-баннер является активной ссылкой на ту или иную страницу сайта (например, со специальными предложениями).
3. Под баннером расположены кнопки переключения баннеров. Кнопка, соответствующая текущему баннеру, выделена другим цветом (блок 1 на рисунке).
4. Под баннером и над кнопками располагается прогрессбар: цветная линия, плавно движущаяся слева направо по мере показа каждого баннера. По аналогии с прогрессбаром в программе-видеоплеере при воспроизведении ролика. Это блок 2 на рисунке.

Вот что нарисовал дизайнер, и требовалось реализовать:

image

Нашлась подходящая библиотека: это плагин Cycle2 для jQuery.

Ссылка на сайт плагина с подробной документацией и примерами: http://jquery.malsup.com/cycle2/.

Ссылка на страницу скачивания плагина: http://jquery.malsup.com/cycle2/download/.

Реализация баннера

Ознакомиться со всеми тонкостями и настройками при использовании плагина Cycle2 вы можете на странице документации: http://jquery.malsup.com/cycle2/api/, либо изучив примеры: http://jquery.malsup.com/cycle2/demo/. Мы же разберем решение только нашей задачи.

В секции head страницы добавим ссылки на jQuery и Cycle2. На нашем сайте они лежат в каталоге /js/:

<script src="/js/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="/js/jquery.cycle2.min.js"></script>

HTML-код для пяти баннеров на странице выглядит так:

<div id="content-ob"
 class="cycle-slideshow"
 data-cycle-fx="scrollHorz"
 data-cycle-timeout="10000"
 data-cycle-speed="1000"
 data-cycle-slides="a"
 data-cycle-pager=".custom-pager"
 data-cycle-pager-template=" <a href=# class='custom-pager-button'> </a>"
 >
        <a href="/page1.html"><img src="/img/pic1.jpg" /></a>
        <a href="/page2.html"><img src="/img/pic2.jpg" /></a>
        <a href="/page3.html"><img src="/img/pic3.jpg" /></a>
        <a href="/page4.html"><img src="/img/pic4.jpg" /></a>
        <a href="/page5.html"><img src="/img/pic5.jpg" /></a>
        <div id="progress"></div>
        <div class="custom-pager"></div>
 </div>

Разберем html-код.

Блок баннера заключен в тег div c id= «content-ob». Этот id мы используем в css-файле для задания некоторых индивидуальных параметров расположения блока, не имеющих отношения к нашей статье.

  • Атрибут
    class= "cycle-slideshow"
    отвечает за преобразование нашего блока в листающийся баннер. Этот атрибут важен, при его наличии библиотека Cycle2 преобразует блок.
  • data-cycle-fx= "scrollHorz"
    — укажем способ перелистывания баннеров по горизонтали.
  • data-cycle-timeout= "10000"
    — время показа каждого баннера в миллисекундах, т.е. у нас 10 секунд на показ баннера.
  • data-cycle-speed= "1000"
    — время на анимацию перелистывания баннера, 1 секунда.
  • data-cycle-slides= "a"
    — этот атрибут указывает, в каком вложенном теге содержатся перелистываемые блоки. Т.к. мы листаем блоки
    <a href= "/pageX.html"><img src= "/img/picX.jpg" /></a>
    , то указан тег a.
  • data-cycle-pager= ".custom-pager"
    — селектор для блока навигационных кнопок. Мы используем нестандартный блок, т.к. стандартный блок нам не подходит по дизайну.
  • data-cycle-pager-template= " <a href=# class='custom-pager-button'> </a>"
    — шаблон кнопки навигации.

Как нетрудно догадаться, строки вида:

<a href="/page1.html"><img src="/img/pic1.jpg" /></a>

<a href="/page2.html"><img src="/img/pic2.jpg" /></a>

 ...

являются переключаемыми баннерами со ссылками на страницы сайта.

Код
<div id= "progress" ></div>
— блок для отрисовки прогрессбара.

Код
<div class= "custom-pager" ></div>
— блок для отрисовки кнопок навигации.

Рассмотрим CSS-стили для нашего баннера

.custom-pager{
/*стиль блока навигации*/
     margin-left:435px;
     margin-top:5px;
     overflow:hidden;    
}

a.custom-pager-button{
    /*стили неактивной кнопки навигации*/
    display:block;
    float:left;
    margin-right:5px;
    width:29px;
    height:13px;
    overflow:hidden;
    background-image:url(/img/newdis/ob-in.png);
    background-position:left top;
    background-repeat:no-repeat;
    cursor: pointer;
}

.custom-pager a.cycle-pager-active{ 
     /*стили для активной кнопки навигации*/
     background-image:url(/img/newdis/ob.png) !important;
     cursor: pointer;
}
.custom-pager > * { cursor: pointer;} /*курсор при наведении на кнопки навигации - как у ссылки*/

#progress { 
/*стиль для прогрессбара*/
margin-top:3px; 
height: 3px; 
width: 0px; 
background: #860b70; 
z-index: 500; 
}

С этими параметрами у нас будет работать все, кроме прогрессбара.

Для реализации прогрессбара был доработан код из примера к Cycle2: http://jquery.malsup.com/cycle2/demo/progress.php.

Реализация анимации прогрессбара

В примере прогрессбар движется от 0 до 100% при показе каждого баннера. Нам же необходимо, чтобы прогрессбар был похож на воспроизведение видео в видеоплеере — двигался бы плавно от 0 до 100% по мере показа всех пяти баннеров.

Вот что получилось в результате:

 
var progress = $('#progress'),
slideshow = $( '.cycle-slideshow' );

/*перед переключением баннера - приостановим движение прогрессбара
в его текущем положении*/
slideshow.on( 'cycle-initialized cycle-before', function( e, opts ) {
	if(opts.slideNum==undefined) number=1; /*на первом баннере вместо номера баннера 
                                               возвращается undefined, подставим первый номер*/
	else number=opts.slideNum;
	number--;
	w=Math.round(100*number/opts.slideCount); /*вычислим текущее положение прогрессбара
                                                   в % относительно предыдущего баннера*/ 
	progress.stop(true).css( 'width', w+'%' ); /*остановим анимацию прогрессбара 
                                                   в найденном положении*/
});

/*
после переключения баннера - возобновим анимацию
от текущего положения прогрессбара к его положению относительно следующего баннера
*/
slideshow.on( 'cycle-initialized cycle-after', function( e, opts ) {
	  if(opts.slideNum==undefined) number=1;/*на первом баннере вместо номера баннера 
                                                возвращается undefined, подставим первый номер*/
	  else number=opts.slideNum;

	  w=Math.round(100*number/opts.slideCount); /*найдем положение прогрессбара в %
                                                     относительно текущего баннера*/
	  if(w>100) w=100; //заглушка на случай ошибки

          /*возобновим анимацию прогрессбара с текущего положения до положения в %
          относительно следующего баннера*/
  	  progress.animate({ width: w+'%' }, opts.timeout, 'linear' );
});
 

Как видно из комментариев к коду, используются обработчики двух событий: начала анимации переключения баннера и конца анимации переключения баннера. В обработчики передается объект opts, содержащий свойства блока баннеров.

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

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

Индекс текущего баннера мы можем узнать с помощью свойства opts.slideNum объекта opts.

Общее число баннеров мы узнаем в свойстве opts.slideCount.

Наконец, указать интервал времени для анимации равным времени показа мы можем, узнав время показа в свойстве opts.timeout. Это значение мы задавали в html-коде с помощью атрибута data-cycle-timeout= «10000».

Задача решена!

Комментарии (2)


  1. xRay
    26.10.2015 22:00

    Чем Owl Carousel 2 не подошел для задуманного?


  1. gydex
    27.10.2015 23:11

    А в Owl Carousel 2 есть возможность плавной отрисовки статус-бара? Мы ее не обнаружили.