Показаны сообщения с ярлыком дизайн. Показать все сообщения
Показаны сообщения с ярлыком дизайн. Показать все сообщения

четверг, 3 мая 2012 г.

Кастомный слайдер на jQuery. Часть 2.

    Продолжение...
    Итак, продолжаем эпопею со слайдером.


Доработка
    На данный момент мы имеем слайдер, который состоит из трех частей: контента, пассивного меню и скроллера изображений. Все действия по доработке будут направлены на максимальное приближение его дизайна и функционала к соответственным свойствам образца от GavickPro.


Мой вариант.
Демо тут - https://sites.google.com/site/groundfored/home/slider

jQuery скрипт
    Начнем со скрипта, который притерпел значительные изменения по сравнению с вариантом из первой части в связи с расширением функциональности слайдера.

function RefreshSlider(index) {
    $('div.ImageContainer .SliderImage').stop(true).hide();

// Останавливаем текущую анимацию контента и очищаем очередь всех последующих анимаций.
    $('div.ContentContainer .SliderContent').stop(true).hide();
    $('div.ContentContainer .SliderContent').css('top', '300px');

    // Запускаем очередь анимации изображений с определенной позиции.
    ImagesAnimation($('div.ImageContainer .SliderImage').eq(index));

    // Запускаем очередь анимации контента с определенной позиции.
    ContentAnimation($('div.ContentContainer .SliderContent').eq(index),
                             $('div.SliderMenu li').eq(index));
};


    RefreshSlider(index) - функция, которая отвечает за "обновление" контента и скроллера изображений. Она имеет единственный управляющий параметр - index (индекс пункта меню) и вызывается всякий раз, когда пользователь осуществляет навигацию по меню или стрелкам слайдера.

function ImagesAnimation(imageItem) {
    imageItem.fadeIn(300).delay(3300).fadeOut(300,function () {
        ImagesAnimation(imageItem.GetSibling());
    });
};

    Немного изменил эту функцию по сравнению с первым вариантом, который был кривовато на скорую руку написан. Теперь рекурсивный вызов в колбеке для .fadeOut().


function BottomAnimation(bottomItem) {
    bottomItem.fadeIn(100);
    bottomItem.animate({ 'left': '-=795px' }, 3000, 'easeOutBounce', function () {
        $(this).delay(3000).fadeOut(300, function () { $(this).css('left', '800px'); });
        BottomAnimation($(this));
    });
};

    BottomAnimation(bottomItem) - функция для анимации нижней "слайдер-строки". В моем исполнении этот элемент функционирует несколько иначе чем в оригинале, но мне так больше понравилось. Для цикличности анимации используется рекурсия в колбек-функции для .animate(). Хочу отметить, что я использовал здесь плагин jQuery - Easing для необходимого мне расширения характеристик поведения функции .animate() (http://gsgd.co.uk/sandbox/jquery/easing/)

$(document).ready(
    function () {
        var imageContainer = $('div.ImageContainer');
        var menuItems = $('div.SliderMenu li');
        var index = 0;
        var leftArrow = $('#LeftArrow');
        var rightArrow = $('#RightArrow');

        $('div .ImageContainer .SliderImage').hide();
        $('div.ContentContainer .SliderContent').css('top', '300px');

        BottomAnimation($('.BottomContainer .BottomContent'));
        ContentAnimation($('div.ContentContainer .SliderContent:first'), $('div.SliderMenu li:first'));
        ImagesAnimation($('div.ImageContainer .SliderImage:first'));

        leftArrow.click(function () {
            index = menuItems.filter('.selected').prev().index();
            index = (index != -1) ? index : menuItems.last().index();
            RefreshSlider(index);
        });

        rightArrow.click(function () {
            index = menuItems.filter('.selected').next().index();
            index = (index != -1) ? index : menuItems.first().index();
            RefreshSlider(index);
        });

        menuItems.click(function () {
            index = menuItems.index($(this));
            RefreshSlider(index);
        });
    });

    .ready() - функция  - также несколько изменилась. Добавились 5 переменных для удобства использования в функциях вместо селекторов. В секции "инициализации" к функциям анимации контента и изображений добавилась функция анимации нижней строки.
    За функционирование навигации по меню и стрелкам отвечают реализации в обработчиках событий .click() для соответствующих элементов разметки. Расписывать подробно пояснения к коду внутри обработчиков я не буду. Если вам что-либо не понятно - у меня для вас печальные новости... :) Отмечу лишь, что в конце каждой функции вызывается RefreshSlider(index), о которой было сказано выше.

Разметка 
    Далее я приведу вариант моей XHTML-разметки. Это лишь один из миллиарда возможных вариантов разметки, который не претендует на звание самого совершенного, но является рабочим и соответствует моим нуждам.

<div id="Slider">
    <div class="SliderBody">
...

    Я использовал стандартную блочную верстку и все обернул в div-ы. Div с классом "SliderBody" - обертка для всего функционального содержимого.

...
<div class="SliderArrow" id="LeftArrow"><p><</p></div>
<div class="SliderArrow" id="RightArrow"><p>></p></div>
<div id="CenterSection">
...

    Далее идут стрелки навигации. Они выполнены просто в виде символов "<" и ">". Правильнее было бы их нарисовать, но, как я писал прежде в первой части, мне в принципе не понятна функциональная необходимость их наличия, поэтому я не стал заморачиваться по этому поводу.
   Следует отметить, что при таком подходе к реализации кнопок потребуется уделить больше внимания страничной разметке и CSS, по сравнению с вариантом, если бы кнопки были рисоваными.
    На данном этапе по моему замыслу тело слайдера конструктивно делится на три части: два блока стрелок и центральная часть между ними с айди "CenterSection".

...
<div class="ContentContainer">
<div class="SliderContent" title="Первая панель">
<h1>...</h1>
<p>...</p>
<a href="..."></a>
</div>

<div class="SliderContent" title="Вторая панель">
...
</div>
...
</div>
...

    Далее по коду - блок с классом "ContentContainer", который содержит в себе наиболее информативную для пользователей составляющую наполнения слайдера - заголовки <h1>, текстовые блоки-абзацы <p> и ссылки <a>. Все перечисленные элементы разметки сгруппированы и размещены в блоках с классом "SliderContent".
    Блок контента является одной из четырех составляющих вышеупомянутого центрального блока слайдера (блока с айди "CenterSection"), другими словами - тело центрального блока конструктивно я разделил на четыре части, о которых будет сказано далее.

...
<div class="ImageContainer">
<div class="SliderImage">
<img src="..." />
</div>

       <div class="SliderImage">
...
</div>
...
</div>
...

    Блок с классом "ImageContainer" - это блок изображений справа. Второй внутренний блок центральной секции слайдера. Тут все просто - конструктивно состоит из div-ов класса "SliderImage", которые содержат элементы <img>.

...
<div class="SliderMenu">
<h2>...</h2>
       <ul>
<li>...</li>
...
       </ul>
</div>
...

   Далее идет третья составляющая часть центрального блока - блок меню "SliderMenu". Внутри содержится заголовок для меню <h2> и элемент списка - <ul>, в котором формируется контекст меню из центральной части слайдера.

...
<div id="BottomLine">
<div class="BottomContainer">
<span>Engineering & Development: </span>
<span class="BottomContent">...<a href="..."> </a></span>
</div>
</div>
...

    Четвертый и последний элемент центрального блока слайдера - "слайдер-строка" о которой я упоминал в первом посте. Возможно можно было обойтись меньшим количеством div-ов, но в данном случае, как видно, число div-ов не критично. Создавая этот элемент, как и в случае со стрелками навигации, я особо не старался, просто сделал, чтоб слайдер максимально соответствовал оригиналу.
    В блоке с классом "BottomContainer" содержатся элементы <span> и <a>.

...
</div>
</div>
</div>


    Ну и в завершении - не забыть закрыть все открытые div-ы.
    Конечно без CSS-стилей "картина" выглядит не полной, но это пост вышел слишком объемным. Возможно CSS отдельно распишу позже.

вторник, 10 января 2012 г.

Кастомный слайдер на jQuery. Часть 1.

          Однажды, пребывая в поиске дизайнерских решений для рабочего проекта, набрел на слайдер из Joomla-шаблона от GavickPro (на момент написания поста демо-сайт был доступен по адресу http://demo.gavick.com/joomla16/apr2010).

Сам слайдер.

         Это решение привлекло к себе мое внимание своей уникальностью, так как ничего подобного я не нашел в сети. Слайдеров в интернете было великое множество, но все они были примитивными прокрутчиками галерей изображений и в виде готовых решений-сборок, которые подкорректировать под свои нужды было очень сложно без знаний и опыта веб-разработки.
Итак, несмотря на то, что мне буквально с первого взгляда понравился увиденный слайдер, нужно было ответить себе на вопрос – как собственно я собираюсь его реализовать (поскольку я кодер и к дизайну имею весьма посредственное отношение)? Ответ - потихоньку :).

- “Профессор здесь живет?” -“Нет!” - “И тем не менее – позовите.” ©

Хотя соображений по поводу реализации не было, но, тем не менее, слайдер с демо-сайта мозолил глаза. Ну, собственно, знания javascript маленькие, но все-таки были, и я изначально нехотя начал думать о тяжеловесной реализации используя связку javascript/DOM.

jQuery

Буквально за пару дней до того, как я увидел слайдер, мне удалось немного узнать о jQuery, и я решил использовать эту надстройку над DOM. Причин такого решения было несколько. Во-первых, все готовые слайдеры, которые я находил в сети, были реализованы с использованием jQuery. Во-вторых, это удобство использования технологии (гибкость, легковесность кода), ну и в-третьих, почему-то мне сразу была интуитивно очевидна необходимость ее использования.
Потратив день на поиск в сети и изучение материалов по jQuery, которую я вообще не знал в отличии от скрипта, я приступил к реализации.
Конструктивно слайдер состоит из четырех частей, без учета стрелок навигации (необходимость наличия кнопок навигации осталась для меня непонятной, если есть меню? Разве только, как декоративный элемент, чтоб покликать-поиграться). Справа – сам блок слайдера изображений, блок  меню в центре и блок текстового контента слева. Снизу по всей ширине находится, назовем ее так “слайдер-строка” – интересный с точки зрения реализации элемент, который в данном случае я отброшу для упрощения.
На текущий момент меня интересует исключительно дизайн конкретной мастер-страницы а не функционал, поэтому мне нужен некий слайдер-полуфабрикат, максимально упрощенный для данной итерации цикла проектирования, который будет модифицироваться на следующих итерациях.

Разработка

Я буду делать верстку в HTML4 c использованием спецификаций HTML и CSSИтак, мой упрощенный слайдер в первом приближении будет иметь три составных части, которые я обозначу как: контент, меню и изображения. Причем меню будет пока пассивным (также для упрощения).
Мой вариант HTML-разметки выглядит следующим образом:




<div class="SliderBody">         
        <div id="CenterSection">

            <div class="ContentContainer">                 
                <div class="SliderContent" title="Первая панель">                     
                        <h2>Первая панель</h2>                           
                        <p>Абзац. Тект1.</p>                                          
                </div>                 
               
      
            </div>

            <div class="ImageContainer">
                <div class="SliderImage">            
                    <img alt="" src="../../Content/Pic/Slider/simage1.png" />
                </div>
               
            </div>

            <div class="SliderMenu">
                <ul>
                    <li>MenuItem1</li>
                   
                </ul>
            </div>     
        </div>  
    </div>

Здесь нет ничего сложного. Все предельно упрощено и ясно. ContentContainer – блок для контента, ImageContainer – блок изображений, SliderMenu – блок меню.
Следует отметить, что контент-блоки имеют абсолютное позиционирование относительно родительского блока и сдвинуты вниз – за пределы слайдера. Таким образом, в процессе анимации они будут подыматься снизу и прятаться обратно.
CSS приводить не буду, так как кроме нюанса с контентом, вроде, больше ничего особенного нет. Кому надо – подождет вторую часть статьи, где будет полностью готовый слайдер, кому лень ждать – напишет сам (и правильно сделает).
Наша задача – обеспечить циклическую прокрутку контента в вышеперечисленных трех блоках. Как выяснилось немного позже – основной проблемой, лично для меня с минимальными знаниями jQuery, было обеспечение цикличности прокрутки.
Итак, скрипт:

(function ($) {

    $.fn.GetSibling = function () {
        return ($(this).next().length > 0) ? $(this).next() : $(this).siblings(':first');
    };

})(jQuery)

function ImagesAnimation(elem) {
    elem.delay(1800).fadeIn(300, function () {
        elem.delay(1500).fadeOut(300);
        ImagesAnimation(elem.GetSibling());
    });
};

function ContentAnimation(contentItem, menuItem) {
        contentItem.show().animate({ 'top': '-=250px' }, { duration: 200 });
        menuItem.addClass('selected').siblings().removeClass('selected');
        contentItem.delay(2000).animate({ 'top': '+=250px' }, { duration: 200, complete: function () {
            ContentAnimation(contentItem.GetSibling(), menuItem.GetSibling());
        }
        });
};

$(document).ready(
    function () {
       
        $('div .ImageContainer .SliderImage').hide();
        $('div.ContentContainer .SliderContent').css('top', '300px');

        ContentAnimation($('div.ContentContainer .SliderContent:first'), $('div.SliderMenu li:first'));
        ImagesAnimation($('div.ImageContainer .SliderImage:first'));

    });

Разбираем по порядку.

.GetSibling() – кастомный метод-расширения, котрый возвращает, по ситуации, следующего или первого родственника для вызывающего элемента DOM.
Если вас пугает внешний вид единственной инструкции данного метода – у меня для вас печальные новости … :).
На самом деле, я не уверен, в силу своих скромных знаний jQuery, правильно ли называть эту функцию расширяющим методом. Просто очень смахивает на метод-расширения родного С#.

ImagesAnimation(elem) – функция для прокрутки изображений. Обратите внимание на рекурсивный вызов в колбек-функции для .fadeIn().

ContentAnimation(contentItem, menuItem) – функция аналогичная предыдущей для прохода по контенту и по меню. Также вызывает саму себя в колбек-функции для .animate().
Здесь следует уделить внимание синтаксическим особенностям вызова колбек-функции для .animate(). Колбек-функция задается в опциях конфигурации через complete.


И наконец,  .ready()-функция для DOM по готовности вызывает вышеперечисленные функции прокрутки. Прячет все изображения и сдвигает абсолютно-позиционированые блоки контента вниз на 300 точек (Без явного указания сдвига наблюдались глюки в Опере).

Продолжение следует...

Ccылки

Ссылки на ресурсы, которые помогли в изучении jQuery, да и вообще во всем макропроцессе.
http://jsfiddle.net/ - ну и Фидель :), чтоб все протестировать на лету (очень помог мне).