Листалка картинок на mootools

Среда, 08 Декабрь 2010

 

В данной статье будет описан принцип создания вот такой галереи
Листалка картинок на mootools, в которой есть возможность перелистывания изображений.

 

И так для начала о HTML разметке, с которой будет работать Javascript. Разметка довольно простая, основной контейнер с id WRAPPER, в который помещены еще два контейнера, в одном содержится тег IMG для отображения полноразмерного изображения, а во втором миниатюры. И еще не забываем подключить CSS стили, библиотеку mootools, и сам скрипт содержащий функции для работы листалки.

 

Между <head></head> :

 

  •  
  • <link rel="stylesheet" href="css/style.css" type="text/css" media="screen" />
  • <script type="text/javascript" src="js/mootools-1.2.4-core-yc.js"></script>
  • <script type="text/javascript" src="js/moo-list.js"></script>
  •  

 

Код HTML разметки выглядит так:

 

  •  
  • <body>
  • <div id="wrapper">
  • <div id="view"><img alt="" src="img/2425.jpg"/></div>
  • <div id="thumb">
  • <a href="http://cleverscript.ru"><img alt="" src="img/tumb_2425.jpg"/></a>
  • <a href="http://cleverscript.ru"><img alt="" src="img/tumb_6398.jpg" class="last"/></a>
  • <a href="http://cleverscript.ru"><img alt="" src="img/tumb_2568.jpg"/></a>
  • <a href="http://cleverscript.ru"><img alt="" src="img/tumb_4077.JPG" class="last"/></a>
  • <a href="http://cleverscript.ru"><img alt="" src="img/tumb_9864.JPG"/></a>
  • <a href="http://cleverscript.ru"><img alt="" src="img/tumb_9062.JPG" class="last"/></a>
  • <a href="http://cleverscript.ru"><img alt="" src="img/tumb_3646.jpg"/></a>
  • <a href="http://cleverscript.ru"><img alt="" src="img/tumb_6695.jpg" class="last"/></a>
  • <a href="http://cleverscript.ru"><img alt="" src="img/tumb_9026.jpg"/></a>
  • <a href="http://cleverscript.ru"><img alt="" src="img/tumb_2642.jpg" class="last"/></a>
  • <p class="cb"></p>
  • </div>
  • <p class="cb"></p>
  • </div>
  • </body>
  •  

 

Обязательные идентификаторы:

 

 

Теперь поговорим о CSS стилях. Файл стилей содержит правила для элементов по умолчанию, а также правила в классах которые будут назнаячатся нужным элементам динамически в процессе взаимодействия пользователя и галереи, для создания эффекта интерактивности.

 

Код CSS правил:

 

  •  
  • html, body {
  • width: 100%;
  • padding: 0;
  • margin: 0;
  • font: 12px Arial, Helvetica, sans-serif;
  • color: #333;
  • height: 100%;
  • text-align: center;
  • }
  • #wrapper{
  • width:764px;
  • margin:60px auto 0 auto;
  • text-align:left;
  • padding-bottom:40px;
  • position:relative;
  • }
  • #view{
  • float: left;
  • margin-right: 20px;
  • overflow: hidden;
  • width: 573px;
  • background: url("../img/ajax-loader.gif") no-repeat scroll 270px 170px;
  • }
  • #thumb{
  • float: left;
  • overflow: hidden;
  • width: 171px;
  • }
  • #thumb img {
  • margin: 0 15px 15px 0;
  • }
  • #thumb .last {
  • margin-right: 0;
  • }
  • .active-thumb{ border:5px solid #ee2154; height:45px; width:65px;}
  •  
  • #nav{height:30px; width:90px; position:absolute; bottom:0; left:241px;}
  • #last, #next{display:block; height:30px; width:30px;}
  • #last{float:left;background:url(../img/last-no.png) left center no-repeat;}
  • #next{float:right;background:url(../img/next.png) right center no-repeat;cursor:pointer;}
  •  
  • .last-act{background:url(../img/last.png) left center no-repeat !important; cursor:pointer !important;}
  • .next-no{background:url(../img/next-no.png) right center no-repeat !important; cursor:default !important;}
  •  

 

И так по порядку о важных моментах...

 

Для body - выставляем выравнивание текста по центру, это необходимо для того что бы в IE6 блок с контентом wrapper выровнялся по центру окна браузера.

 

Для #wrapper - выставляем фиксированную ширину, для того что бы браузер правильно расчитал margn: 60px auto; переопределяем выравнивание текста, добавляем внутреннюю рамку по нижнему краю, эта область будет знята кнопками листания, которые будут позиционироватся в этом блоке абсолютно, а также обязательно ставим блоку position:relative;

 

Для #view - здесь все просто, следует только обратить внимание на overflow: hidden;, это на тот случай если отображаемое полноразмерное изображение будет шире этого блока, а также на свойство background здесь ставим блоку фоновой картинкой ajax-loader.gif, который будет крутится пока картинка подгружается.

 

Для #thumb, #thumb img, #thumb .last - тут все ясно.

 

Для .active-thumb - а это первый динамически присваиваемый класс, для миниатюры по которой кликнет пользователь, берем ее в 5ти пиксельную крассную рамку и уменьшаем на эту ширину и высоту ее размеры.

 

Для #nav - тут все просто, абсолютное позиционирование блока со стрелками по центру блока #wrapper.

 

Для #last, #next - размеры кнопок.

 

Для #last, #next - фоновые картинки для кнопок, а также для кнопки next cursor:pointer;, для #last при первой загрузке это не нужно.

 

Для .last-act - второй класс который присваивается кнопке с id #last динамически, начиная с того момента как пользователь пролистал с первой фотографии на вторую, меняем фоновое изображение и поведение курсора мыши, тем самым показывая что кнопка стала активной и есть возможность пролитать обратно.

 

Для .next-no - третий класс который присваивается кнопке с id #next динамически, с того момента как пользователь пролистал до последней фотографии. Меняем фон и убираем cursor:pointer;, показывая этим что кнопка не активна и листать в перед уже некуда, только обратно.

 

Со стилями все, теперь о Javascript

 

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

 

И так создаем событие для window - domready, при котором объявляем переменные содержащие в себе такие объекты DOM как:

 

 

  •  
  • window.addEvent('domready',function(){
  • var i = 0;
  • var wrapper = $('wrapper');
  • var view = $('view');
  • var img = $$('#thumb img');
  • var nav = new Element('div', {id:'nav', html:'<span id="last"></span><span id="next"></span>'});
  • nav.inject(wrapper);
  • });
  •  

 

Здесь i - это счетчик текущего элемента массива, при листании в перед увеличиваем его значение на 1, при листании обратно, уменьшаем значение на 1, а при клике по миниатюре присваиваем этой переменной значение индекса элемента миниатюры.

 

В переменную img - заносим массив миниатюр

 

nav - создаем новый узел DOM, присваивая ему id:nav и помещая в него html содержащий кнопки с идентификаторами last и next, затем помещаем этот узел в элемент c id wrapper, используя для этого mootools функцию inject

 

Итак теперь все основные узлы для манипулирования получены, также определена переменная счетчик, теперь необходимо стрелкам и превью назначить события click по которому нужно определить значение переменной i, и передать его в функцию list(nid); которая будет описана ниже. И так код для "управляющих" элементов:

 

  •  
  • $('next').addEvent('click',function(e){
  • if(i>=img.length-1){
  • e.stop();
  • }else{
  • i++
  • list(nid);
  • }
  • });
  • $('last').addEvent('click',function(e){
  • if(i==0){
  • e.stop();
  • }else{
  • i--
  • list(nid);
  • }
  • });
  •  
  • img.each(function(el,i){
  • if(el.getParent('a')){el.getParent('a').addEvent('click',function(e){e.stop();});}
  • el.addEvent('click', function(){list(nid);});
  • });
  •  

 

Здесь кнопкам с id next и last, присваиваем событие click и составляем условия, от которых будет зависить передаваемое функции list(nid); значение i, которое уазывает на индекс миниатюры в массиве img который мы сформировали в начале программы (по событию domready).

 

Условие для кнопки next: если текущее значение i БОЛЬШЕ или РАВНО значению индекса последнего элемента массива превьюшек img, то отключаем событие клика на этой кнопке, то есть это ситуация когда пользователь долистал до последней фотографии. Если же условие не выполняется i МЕНЬШЕ и НЕ РАВНО значению интекса последнего элемента массива, то увеличиваем i на единицу, и передаем в функцию list(nid); интекс следующего элемента массива, тоесть смещаемся по сассиву img к следующей превью.

 

Условие для кнопки last: если текущее значение i РАВНО ноль, то отключаем событие клика на этой кнопке, то есть это ситуация когда страница загружена и пользователь еще не пролистнул ни одной фотографии, следовательно листать обратно некуда так как мы находимся на первом элементе массива img который и равен нолю. Если же условие не выполняется i НЕ РАВНО ноль, то уменьшаем значение i на единицу, и передаем это значение в функцию list(nid); то есть смещаемся от текущего индекса элемента масиива img к предидущему.

 

Условие для превью: здесь немного иначе, здесь для каждой превью в цикле each присваиваем событие click и проверяем если у превью на которой осуществлен click, есть родительский элемент el.getParent('a') то назначаем ему событие click и отменяем его, проще говоря если превью находится в теге <a> то блокируем переход по ссылки при щелчке. Ниже этого условия назначаем событие для превью и по клику передаем в функцию list(nid); индек превью по которой осуществлен click.

 

С управлением все, теперь поговорим о функции list(nid); которая принимает индекс, производит необходимые манипуляции с кнопками при определенных условиях, а также вызывает следующие две функции которые будут описаны ниже.

 

Код функции list(nid);

 

  •  
  • function list(nid){
  • i = nid;
  • display(img[i]);
  • thumbStyle(img,i)
  • if(i==0){
  • $('last').removeClass('last-act');
  • $('next').removeClass('next-no');
  • }else{
  • if(i==img.length-1){
  • $('next').addClass('next-no');
  • }else{
  • $('next').removeClass('next-no');
  • }
  • $('last').addClass('last-act');
  • }
  • }
  •  

 

Здесь i присваиваем переданное функции значение индекса, передаем в функцию display(img[i]); обьект превью с индексом равным полученному значеню, а также вызываем функцию thumbStyle(img,i) передавая ей массив превью и индекс. Ниже составлены условия, при которых кнопкам присваиваются CSS классы, которые изменят отображение кнопок.

 

Если i РАВНО ноль, то у кнопки last удаляем класс last-act, то есть делаем кнопку неактивной, ситуация когда пользователь еще не пролистал ни одной фотографии, также удаляем класс next-no для кнопки next, при нахождении на первой фотографии мы всегда должны иметь активную кнопку next для листания в перед.

 

Если i НЕ РАВНО ноль, то кнопке last ВСЕГДА присваиваем класс last-act, потому что можно листать обратно, и формируем следующую группу условий, если i РАВНО значению индекса последнего элемента массива превью, то кнопке next присваиваем класс next-no, который сделает ее неактивной, ситуация когда ползователь долистал до последней фотографии. Если же i НЕ РАВНО ноль, то удаляем этот класс у кнопки next, так как листать в перед есть куда.

 

На этом этапе код выглядит следующим образом:

 

  •  
  • window.addEvent('domready',function(){
  • var i = 0;
  • var wrapper = $('wrapper');
  • var view = $('view');
  • var img = $$('#thumb img');
  • var nav = new Element('div', {id:'nav', html:'<span id="last"></span><span id="next"></span>'});
  • nav.inject(wrapper);
  •  
  • function display(el){
  • //...
  • }
  •  
  • function thumbStyle(img,e){
  • //...
  • }
  •  
  • function list(nid){
  • i = nid;
  • display(img[i]);
  • thumbStyle(img,i)
  • if(i==0){
  • $('last').removeClass('last-act');
  • $('next').removeClass('next-no');
  • }else{
  • if(i==img.length-1){
  • $('next').addClass('next-no');
  • }else{
  • $('next').removeClass('next-no');
  • }
  • $('last').addClass('last-act');
  • }
  • }
  •  
  • $('next').addEvent('click',function(e){
  • if(i>=img.length-1){
  • e.stop();
  • }else{
  • i++
  • list(i);
  • }
  • });
  • $('last').addEvent('click',function(e){
  • if(i==0){
  • e.stop();
  • }else{
  • i--
  • list(i);
  • }
  • });
  •  
  • img.each(function(el,i){
  • if(el.getParent('a')){el.getParent('a').addEvent('click',function(e){e.stop();});}
  • el.addEvent('click', function(){list(i);});
  • });
  •  
  • });
  •  

 

Осталось описать еще две функции которые мы вызывам из функции list(nid);

 

И так от простого к сложному, функция thumbStyle(el,e)

 

Код функции thumbStyle(img,e)

 

  •  
  • function thumbStyle(img,e){
  • img.each(function(el,i){
  • if(el.hasClass('active-thumb')){el.removeClass('active-thumb');}
  • if(e==i){el.addClass('active-thumb');}
  • });
  • }
  •  

 

Эта функция принимает массив превью img, а так же индекс текущего изображения, проходится по массиву проверяя есть ли у элементов класс active-thumb и если есть то удаляет его, назначая этот клас только тому элементу у которого индекс равен полученному значению el то есть текущему i. Этот класс CSS добавляет рамку вокруг текущего элемента (превью).

 

Теперь функция display(el).

 

Код функции display(el)

 

  •  
  • function display(el){
  • var src = el.getProperty('src').toString().replace('tumb_', '');
  • var img = view.getChildren('img')[0];
  •  
  • view.setStyles({height: img.getSize().y+'px'});
  •  
  • img.addEvent('load', function(){
  • view.setStyles({height: img.getSize().y+'px'});
  • img.set('tween', {
  • duration: 450,
  • onStart: function(){},
  • onComplete: function(){}
  • }).tween('opacity', 1);
  • });
  •  
  • img.set('tween', {
  • duration: 350,
  • onStart: function(){},
  • onComplete: function(){
  • img.setProperty('src', src);
  • }
  • }).tween('opacity', 0);
  •  
  • }
  •  

 

Эта функция принимает обьект превью, сформированный в функции list(); получает из него атрибут SRC, приводит его к строковому значению и удаляет часть строки - в имени файла, тоесть все превью имеют такое имя файла например tumb_2356.jpg, а имя файла полноразмерного изображения будет 2356.jpg.

 

Таким образом формируется переменная src, которая будет содержать путь к полноразмерному изображению и значение этой переменной будет подставлено в параметр SRC к IMG в блоке с id view для этого ниже определения переменной src, формируем переменную img которая и будет содержать объект IMG из контейнера с id view.

 

Далее контейнеру view, устанавливаем высоту равную высоте находящегося в нем изображения, это сделано для того что бы когда скроется изображение, контейнер не свернулся и в нем фоном крутился ajax-loader.gif.

 

Далее объекту IMG содержащегося в переменной img присваиваем событие load - это событие произойдет когда файл изображения полностью загрузится в тег документа IMG. По наступленю этого события, заново устанавливаем высоту родительского элемента view, получив размер загруженного изображения.

 

Внимание!!! Расчет размеров изображения нужно производить только после их загрузки, то есть после события onload узла IMG, иначе браузер не в состоянии определить его размеры!!! И так после того как картинка загрузилась плавно меняем ее прозрачность с ноля до единицы.

 

Перед этим событием onload, выполняется сначало этот код:

 

  •  
  • img.set('tween', {
  • duration: 350,
  • onStart: function(){},
  • onComplete: function(){
  • img.setProperty('src', src);
  • }
  • }).tween('opacity', 0);
  •  

 

Который сначало плавно растворяет текущее изображение, и после его полного растворения, когда opacity достигнет ноля, меняет у изображения текущий параметр SRC на новый, в следствии чего начинает загружатся новое полноразмерное изображение, и полсле его полной загрузки onload, срабатывает tween, который начинает плавно менять прозрачность до единицы, тоесть полной непрозрачности.

 

Таким образом пользователь не видит как полноразмерное изображение загружается, в это время он видит крутящийся ajax-loader.gif, установленный фоном у развернутого родительского контейнера:)).

 

Полный код выглядит следующим образом:

 

  •  
  • window.addEvent('domready',function(){
  • var i = 0;
  • var wrapper = $('wrapper');
  • var view = $('view');
  • var img = $$('#thumb img');
  • var nav = new Element('div', {id:'nav', html:'<span id="last"></span><span id="next"></span>'});
  • nav.inject(wrapper);
  •  
  • function display(el){
  • var src = el.getProperty('src').toString().replace('tumb_', '');
  • var img = view.getChildren('img')[0];
  •  
  • view.setStyles({height: img.getSize().y+'px'});
  •  
  • img.addEvent('load', function(){
  • view.setStyles({height: img.getSize().y+'px'});
  • img.set('tween', {
  • duration: 450,
  • onStart: function(){},
  • onComplete: function(){}
  • }).tween('opacity', 1);
  • });
  •  
  • img.set('tween', {
  • duration: 350,
  • onStart: function(){},
  • onComplete: function(){
  • img.setProperty('src', src);
  • }
  • }).tween('opacity', 0);
  •  
  • }
  •  
  • function thumbStyle(img,e){
  • img.each(function(el,i){
  • if(el.hasClass('active-thumb')){el.removeClass('active-thumb');}
  • if(e==i){el.addClass('active-thumb');}
  • });
  • }
  •  
  • function list(nid){
  • i = nid;
  • display(img[i]);
  • thumbStyle(img,i)
  • if(i==0){
  • $('last').removeClass('last-act');
  • $('next').removeClass('next-no');
  • }else{
  • if(i==img.length-1){
  • $('next').addClass('next-no');
  • }else{
  • $('next').removeClass('next-no');
  • }
  • $('last').addClass('last-act');
  • }
  • }
  •  
  • $('next').addEvent('click',function(e){
  • if(i>=img.length-1){
  • e.stop();
  • }else{
  • i++
  • list(i);
  • }
  • });
  • $('last').addEvent('click',function(e){
  • if(i==0){
  • e.stop();
  • }else{
  • i--
  • list(i);
  • }
  • });
  •  
  • img.each(function(el,i){
  • if(el.getParent('a')){el.getParent('a').addEvent('click',function(e){e.stop();});}
  • el.addEvent('click', function(){list(i);});
  • });
  •  
  • });
  •  

 

На этом все, всем спасибо кто дочитал:)), если есть вопросы задавайти их в комментариях!

 

Demo

 

Download

 

PS. И не забудьте подписаться на ленту новостей RSS

Метки:

Комментарии 

 
anonim Среда, 05 Январь 2011

If you could e-mail me with a few suggestions on just how you made your blog look this excellent, I would be grateful.

 

 
 
anonim Среда, 05 Январь 2011

Ask here

 

 
 
anonim Пятница, 28 Январь 2011

Спасибо большое за листалку. Она мне очень пригодилась. Вот только мне еще нужно с title картикни сделать описание под большой картинкой.
Помогите пожалуйста изменить фукцию так чтобы из списка
она брала титл и передавала его в титл большой картинки 2425.jpg и 6398.jpg
А потом этот титл передавался в

 

 
 
anonim Воскресенье, 30 Январь 2011

Рад что листалка пригодилась, добавил возможность о которой вы говорите, но текст описания будет брятся у превью из атрибута alt и передаватся в контейнер с id="title".
Пример: Demo v2
Скачать: Dovnload v2

 

 
 
anonim Пятница, 22 Апрель 2011

Хорошая листалка. Особенно ее усовершенствова ный вариант с текстом подписи к картинке. Однако, здесь явно не хватает кнопки автоматического проигрывания картинок. Пожалуйста, если не трудно, добавьте такую кнопку. Ваша листалка станет вполне законченным продуктом.

 

 
 
anonim Воскресенье, 28 Август 2011

Здравствуйте,
очень интересный скрипт, а можно подробнее с установкой на сайт, для новичков?

 

 
 
anonim Воскресенье, 28 Август 2011

подробнее: подключаете js файлы в head и вывод ваших кртинок делаете через верстку которая здесь http://cleverscript.ru/demo/javascript/mootools/moo-list/

 

 
 
Иван Пятница, 25 Ноябрь 2011

Класный скрипт! Подскажите пожалуйста, как сделать, чтобы превьюшки фоток были не справа вертикально, а сверху от большой фотки и горизонтально? Заранее огромное спасибо! Ответ можно здесь или на e-mail

 

 
 
Иван Пятница, 25 Ноябрь 2011

Подскажите пожалуйста как разместить превьюшки сверху от основной фотки горизонтально? Спасибо!

 

 
 
Иван Пятница, 25 Ноябрь 2011

Также интересует, как будет вести себя лента превьюшек, если фоток много, будет ли прокрутка?

 

 
 
cleverscript Суббота, 26 Ноябрь 2011

Иван, разместить блок с превью в нужном вам расположении можно поменяв верстку или поработав с CSS, ничего сложного не вижу в этом, все что требуется понимать, это принципы HTML и CSS

 

 
 
cleverscript Суббота, 26 Ноябрь 2011

По поводу прокрутки - чтобы она была, вам нужно у блока с превью выставить фиксированную высоту и добавить CSS свойство - overflow:scroll ;

 

 
 
Вадим Понедельник, 20 Февраль 2012

Можно сделать еще так чтоб картинки были спрятаны и тоже листались когда приходит сл. очередь картинок?

 

 

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