Фиксированная навигация с использованием плагина jquery waypoints

Скачать Фиксированная навигация с использованием плагина jquery waypoints
Недавно искали:

GE_Pass

Житель
Регистрация
30.01.14
Сообщения
212
Реакции
49
В данном уроке мы сделаем навигационную панель, которая остается на своем месте при прокрутке содержания страницы. И, конечно же, применим пару хитростей для улучшения внешнего вида и функционала.

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

В данном уроке мы будем использовать элемент HTML5 nav в качестве контейнера для горизонтально списка ссылок. А также опишем, как сделать его более приятным для глаз с помощью CSS.

Но что более важно, мы представим плагин jQuery Waypoints, который обеспечивает дополнительный функционал: по мере прокрутки содержания вниз навигационная лента остается наверху окна просмотра и изменяется индикация текущего раздела. Также мы будем использовать другой плагин, ScrollTo, для обеспечения плавной прокрутки и удобного позиционирования при нажатии пользователем на навигационных ссылках.

Демо: http://ruseller.com/lessons/les1626/demo/index.html
Исходник:
Скрытое содержимое доступно для зарегистрированных пользователей!


Шаг 1. Контейнер для навигации
Несомненно, что вы уже знакомы с большим набором новых элементов введенных HTML5. В данном примере мы используем два из них: : <nav> и <section>. начнем со следующей разметки:

Код:
<!DOCTYPE html>

<html>
  <head>
    <meta charset="UTF-8" />
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <div class=wrapper>
      <h1>Большой заголовок.</h1>
      <nav><!-- Навигация. --></nav>
      <section id="section-1">Текст раздела ...</section>
    </div>
    <!-- Скрипты будут располагаться здесь. -->
  </body>
</html>

Мы будем использовать явное определение ширины для навигационной панели. Она будет на 28px шире контейнера содержания, а ее положение ее выступов обеспечиваются отрицательным левым полем. Также обеспечим слегка закругленные углы верхней грани с помощью border-*-radius и небольшой произвольно определенный отступ.

Код:
nav {
  position: relative;
  width: 928px;
  padding: 2em;
  margin-left: -14px;
  border-top-left-radius: 14px 7px;
  border-top-right-radius: 14px 7px;
}

Затем мы добавляем неупорядоченный список ссылок в панель навигации и устанавливаем для его пунктов свойство display: inline-block, чтобы выводить их в одну линию. Нам не нужны никакие метки списка, поэтому добавим свойство list-style: none.

Код:
<nav>

  <ul>
    <li><a class=nav-link href=#section-1>Section 1</a></li>
    <li><a class=nav-link href=#section-2>Section 2</a></li>
    ...И другие пункты списка...
  </ul>
</nav>

Код:
nav li {

  display: inline-block;
  list-style: none;
}

На данный момент наша панель будет выглядеть примерно так:

img_1.jpg



Шаг 2. Закругленные концы ленты
Теперь, если бы CSS допускал возможность иметь множество псевдо элементов (например, ::after::after), мы бы могли сделать скругленные концы навигационной панели семантически правильным способом. Но, нам придется использовать два выпадающих из семантики элемента div в конце nav. Определим для них классыnav-left и nav-right. Они имеют 14px ширины и 14px высоты, позиционируются абсолютно в 14px от низаnav.

Семейство свойств border-radius может принимать 2 значения для каждого угла. Также можно использовать проценты для установки ширины, что является достаточно удобным методом - позволяет автоматически адаптировать радиус закругления к изменениям размеров прямоугольника.

Небольшие “тени”, которые завершают создание внешнего вида панели, созданы с помощью псевдо-элементов ::after. Их высота и ширина, также как и радиус закругления рамки устанавливаются в процентах.

Код:
/* поменяйте ‘left’ на ‘right’ для другого конца навигационной ленты */

.nav-left {
  position: absolute;
  left: 0;  bottom: -14px;
  width: 14px;  height: 14px;
  background: #848a6a;
  border-bottom-left-radius: 100% 50%;
}
.nav-left::after {
  content: '';
  position: absolute;
  right: 0;
  width: 66%;  height: 66%;
  background: #000;
  border-top-left-radius: 100% 50%;
  border-bottom-left-radius: 100% 50%;
}

Теперь панель навигации будет выглядеть так:

img_2.jpg



Шаг 3. Скрипт
Для достижения эффекта плавающего блока мы будем использовать плагин jQuery Waypoints (автор Caleb Troughton). Его единственным назначением является запуск событий при прокручивании пользователем до определенных элементов. Он очень простой в использовании, но предлагает достаточно большой набор возможностей (смотрите примеры на его домашней странице).

Включаем jQuery и Waypoints в код страницы.

Первое, что нужно сделать, зарегистрировать точку с помощью метода .waypoint()для элемента. Конечно, ничего не происходит - нужно определить функцию для обработки события. Самый простой способ определения функции -передача параметров функции .waypoint().

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

Код:
$(function() {                     // После загрузки страницы

  $('nav').waypoint(               // Создаем точку
    function() {
      alert("Mjxrf достигнута.");
    }
  )
});

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

Код:
<div class="nav-container">

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

В CSS создаем следующее правило.
Код:
.sticky {
  position: fixed;
  top: 0;
}

И изменяем скрипт следующим образом:


Код:
$(function() {
  var nav_container = $(".nav-container");
  var nav = $("nav");
  nav_container.waypoint({
    handler: function(event, direction) {
        nav.toggleClass('sticky', direction=='down');
    }
  });
});

Вы вполне правомочны задать вопрос: "Что здесь происходит?". Вероятно вы догадались, что мы привязываем точку к контейнеру nav-container, но в этот раз мы пользуемся другим способом. Вместо непосредственной передачи функции обработчика методу .waypoint() мы инкапсулируем её в объект. Большой разницы для функционирования нет. Объект, который мы передаем, может содержать несколько других опций, что сделает его достаточно удобным для использования в дальнейшем.

Функция обработчик, которую мы определили, принимает два параметра. Первый - стандартный объект jQuery event, который нам не интересен. Второй - специфичный для плагина Waypoints, является строкой‘down’ или ‘up’, в зависимости от направления прокручивания, которым достигается точка.

Знания о направлении прокрутки является важной информацией, которая позволяет определять различное поведение. В теле обработчика мы используем сравнительно малоизвестный вариант метода jQuery.toggleClass(): второй параметр определяет условия для добавления или удаления класса. Когда пользователь прокручивает страницу вниз, выражение direction===’down’ будет иметь значение true, и наше навигационная панель получит класс sticky, который зафиксирует её наверху окна просмотра. Как только пользователь прокрутит страницу обратно, класс удалится, и навигационная панель станет на свое место.

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

Код:
if (direction == 'down')

  nav_container.css({ 'height':nav.outerHeight() });
else
  nav_container.css({ 'height':'auto' });

Решение вполне очевидно: мы используем nav-container как заполнитель места. Когда происходит прокрутка вниз мы увеличиваем высоту и содержание, расположенное ниже, остается на месте. Чтобы метод работал, нужно любые вертикальные поля, которые могут потребоваться для панели навигации должны использоваться для элемента nav-container, а не для элемента nav.



Шаг 4. Вертикальное смещение
Если вы задумывались над процессом, то существует множество случаев, когда запуск события при точном достижении элементом границы окна просмотра, является нежелательным. Плагин Waypoints обеспечивает удобную опцию для решения задачи: offset. Например:

Код:
nav.waypoint( {

  handler: …,
  offset: 50
} )

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

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

Первое, что надо учесть - дополнительное пространство над фиксированным элементом. Использование переменной offset облегчает решение: для смещения в 15px добавляем offset:15px к опциям метода.waypoint() и меняем top:0px на top:15px в правилах класса .sticky.

Небольшой градиент над панелью навигации может улучшить дизайн. Добавить его легко с помощью дополнительного элемента div в элемент nav и кода CSS для него:

Код:
.sticky .nav-above {

  position: absolute;
  top:-15px;
  left:1em;
  right:1em;
  height:15px;
  background: linear-gradient(top, rgba(255,255,255,1) 0%,rgba(255,255,255,0) 100%);
  /* добавляем градиент, если нужно */
}



Шаг 5. Функция смещения
Одна из замечательных возможностей плагина - динамическое определение смещения точки:


Код:
nav.waypoint( {
  handler: …,
  offset: function() {
    return —(nav.outerHeight()+50);
  }
} )

В данном примере обработчик будет запускаться в момент, когда пользователь уже прокрутил страницу на 50px ниже нижней границы элемента (знать высоту элемента не нужно).

Примечание: такие генерируемые смещения (также, как и заданные в процентах) будут вычисляться каждый раз при изменении размеров окна., добавления новых точек или модификации опций точек. Если вы выполняете операции, оказывающие влияние на позиционирование точек (такие как изменение шаблона DOM или страницы) нужно вызывать $.waypoints('refresh') для пересчета позиций.

В контексте нашего урока мы используем данный функционал для плавного выскальзывания навигационной панели сверху:

Код:
var top_spacing = 15;
var waypoint_offset = 50;
nav_container.waypoint({
  handler: function(event, direction) {
    if (direction == 'down') {
      nav_container.css({ 'height' : nav.outerHeight() });
      nav.addClass("sticky")
         .stop()
         .css("top", -nav.outerHeight())
         .animate({"top" : top_spacing});
    } else {
      nav_container.css({ 'height' : 'auto' });
      nav.removeClass("sticky")
         .stop()
         .css("top", nav.outerHeight() + waypoint_offset)
         .animate({"top" : ""});
    }
  },
  offset: function() {
    return &mdash;(nav.outerHeight() + waypoint_offset);
  }
});

Здесь стандартные операции jQuery: добавление или удаление класса sticky к элементу nav, изменяем вертикальное позиционирование с помощью метода .css(), и затем выполняем .animate(). Метод .stop()служит для предотвращения возможных ошибок, очищая очередь событий jQuery.




Шаг 6. Выделение и плавная прокрутка
Очень полезным может оказаться выделение пунктов, соответствующих текущему положению на странице. С помощью плагина Waypoints задача легко решается. Нужно добавить в скрипт следующие строки:

Код:
$(function() {
  …
  // Копируем отсюда…
  var sections = $('section');
  var navigation_links = $('nav a');
  sections.waypoint({
    handler: function(event, direction) {
      // код обработчика
    },
    offset: '35%'
  });
  // …до сюда
});

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

Код, который мы используем в обработчике достаточно очевиден:

Код:
var active_section;
active_section = $(this);
if (direction === "up") active_section = active_section.prev();
var active_link = $('nav a[href="#' + active_section.attr("id") + '"]');
navigation_links.removeClass("selected");
active_link.addClass("selected");

Нам нужно знать, какая секция выводится. Если происходит прокрутка вниз, то секция, которой принадлежит точка, становится активной. При прокручивании наверх в окно просмотра попадает предыдущая секция, поэтому мы используем .prev() для ее выделения. Затем удаляем класс selected со всех ссылок панели навигации перед тем, как установить его для одной ссылки, чей атрибут href соответствует id текущей активной секции.

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

Код:
navigation_links.click( function(event) {
  $.scrollTo(
    $(this).attr("href"),
    {
      duration: 200,
      offset: { 'left':0, 'top':-0.15*$(window).height() }
    }
  );
});

Хотя есть лучшие способы привязки события click, мы используем простейший: .click(). Метод .scrollTo()вызывается также, как и .waypoint(). Он принимает два параметра: цель прокрутки и объект с опциями. Атрибут href нажатой ссылки работает как цель, а выражение используется для установки смещения на 15% от высоты окна просмотра.
 
Назад
Сверху Снизу