Афоризм
Ничто не вечно по луною,
завел мой врач издалека.
Последние статьи

 • Активности Android
Многоэкранные Android приложения
 • Fragment dynamic
Динамическая загрузка фрагментов в Android
 • Fragment lifecycle
Жизненный цикл Fragment'ов в Android
 • Fragment example
Пример Fragment'ов в Android
 • Data Binding
Описание и пример Data Binding
 • Пример MVVM
Пример использования MVVM в Android
 • Компонент TreeTable
Описание компонента TreeTable для Swing
 • Пример TreeTable
Пример использования TreeTable
 • Хранилища Android
Внутренние и внешние хранилища данных
 • Пример SQLite
Пример использования SQLite в Android
 • WebSocket
Описание и пример реализации WebSocket
 • Визуальные компоненты
Улучшен компонент выбора даты из календаря
 • Анимация jQuery
Описание и примеры анимации элементов DOM
 • APK-файл Android
Создание apk-файла для android устройств, .dex файлы
 • платформа JaBricks
Платформа OSGi-приложения JaBricks
Поддержка проекта

Если Вам сайт понравился и помог, то будем признательны за Ваш «посильный» вклад в его поддержку и развитие
 • Yandex.Деньги
  410013796724260

 • Webmoney
  R335386147728
  Z369087728698
Перейти к содержанию jQuery

Анимированная навигация jQuery

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

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

Анимированная панель навигации

Ниже представлены две однотипные панели навигации. Верхняя панель навигации использует изображение, нижняя – только текст. При наведении курсора на элемент навигации верхней панели изображение прокручивается снизу вверх, при покидании элемента – исходное изображение элемента возвращается сверху вниз. Для нижней панели анимация касается только цвета шрифта; поведение текста аналогично при наведении на него курсора мыши и при покидании. Прототип данного примера расположен здесь.

Описание HTML кода анимированной панели

Ниже представлен HTML-код анимированных навигационных панелей, содержащий контейнеры <ul> с несколькими элементами <li>. Контейнеры панелей включены в блок <div>. Все элементы структуры используют css-стили. Использование css-стилей и JavaScript-кодов позволяет создать анимированные навигационные панели.

Обратите внимание, что для верхней навигационной панели определен класс css-стиля "nav_img", обеспечивающий представление ссылки меню в виде кнопки с изображением. Кроме этого, при нажатии на «кнопку» верхней панели вызывается определенный в коде JavaScript метод linkClick, который открывает окно с сообщением нажатия определенного пункта меню, с которым связан параметр метода. При выборе пункта меню нижней панели выполняется перезагрузка страницы с переходом в позицию #nav_panel, которая определена у заголовка данного первого примера в виде невидимой ссылки <a name="nav_panel" />.


<div class="container">
    <ul id="navigation" class="nav_img">
        <li><a href="javascript:linkClick(1)">Главная</a></li>
        <li><a href="javascript:linkClick(2)">Услуги</a></li>
        <li><a href="javascript:linkClick(3)">Продукты</a></li>
        <li><a href="javascript:linkClick(4)">О нас</a></li>
        <li><a href="javascript:linkClick(5)">Контакты</a></li>
    </ul>
    <ul id="navigation">
        <li><a href="#nav_panel">Главная</a></li>
        <li><a href="#nav_panel">Услуги</a></li>
        <li><a href="#nav_panel">Продукты</a></li>
        <li><a href="#nav_panel">О нас</a></li>
        <li><a href="#nav_panel">Контакты</a></li>
    </ul>
</div>
 

На заметку : ссылка на заголовок #nav_panel включается браузерами Google Chrome, Microsoft Edge, Opera (на других не проверял, полагаю и они также) в структуру DOM первого блока <ul> и его первого элемента <li> в виде ссылки, которая должна учитываться в скриптах при формировании интерфейса панели. Если включение ссылки не учитывать, то искажается интерфейс анимированной панели, даже если она одна и не использует изображение (cм. описание блока скриптов <script type="text/javascript">).

Описание CSS-стилей

CSS-стили для анимированной навигационной панели включены в скриптовой блок, которой размещается в теле страницы <body>. Можно было бы конечно загрузить их и из отдельного css-файла. Но создавать отдельный файл для каждого интегрированного в проект примера, на мой взгляд, не очень-то целесообразно, если это можно выполнить описанным ниже способом с использованием библиотеки jQuery, функциональные возможности которой мы здесь представляем.

Загрузка стилей выполняется методом injectCSS, который не входит в состав основной библиотеки jQuery, а включен в отдельную библиотеку jquery.injectCSS.js, которую можно скачать с Github.

Стили навигационной панели определяют размер контейнера (div container) и свойства навигационных элементов <ul> и <li>. Верхняя панель навигации использует изображение a_bg.gif, которое имеет размер 1х80. Визуально изображение разделено на 2 части; вторая часть отображается при наведении курсора. Высота навигационной панели составляет 40px. Обратите внимание, что стиль «ul#navigation a» представлен совместно с «ul#navigation span»; второй стиль, равно как и вторая часть изображения (ul#navigation.nav_img span) используются совместно для теневого изображения кнопок панели, которые появляются при наведении курсора. Т.е. с использованием стилей и скриптов для каждой кнопки панели создается «теневая» кнопка (тег <span>), появление которой реализует java-скрипт при наведении курсора методом hover библиотеки jQuery в скриптовом блоке.

<script type="text/javascript">
$(document).ready(function() {
   $.injectCSS({
      ".container" : {
         'width': '850px',
         'height': '140px',
         'overflow': 'hidden'
      },
      "img" : {
         'border': 'none'
      },
      "ul#navigation" : {
         'padding': '0px',
         'list-style': 'none',
         'font-size': '1.1em',
         'clear': 'both',
         'float': 'left',
         'width': '850px'
      },
      "ul#navigation li" : {
         'overflow': 'hidden',
         'float': 'left', 
         'height': '40px'
      },
      "ul#navigation a, ul#navigation span" : {
         'padding': '10px 20px',
         'float': 'left',
         'text-decoration': 'none',
         'color': '#fff',
         'font-size' : '10pt',
         'text-transform': 'uppercase',
         'clear': 'both',
         'height': '20px',
         'line-height': '20px',
         'background': '#4d4d4d'
      },
      "ul#navigation a" : {
         'color': '#fbc441'
      },
      "ul#navigation span" : {
         'display': 'none'
      },
      "ul#navigation.nav_img span" : {
         'background': 'url(a_bg.gif) repeat-x left top'
      },
      "ul#navigation.nav_img a" : {
         'color': '#555',
         'background': 'url(a_bg.gif) repeat-x left bottom'
      }
   });
});
<script>
 

Описание js-скриптов

Листинг скриптов включает два метода. В методе linkClick выполняется обработка нажатия пункта меню верхней навигационной панели с открытием окна (alert) и выводом сообщения с наименованием кнопки/ссылки. В качестве параметра методу передается номер, по которому в цикле .each определяется позиция ссылки. В селекторе функции jQuery используется фильтрация набора для получения дочерних элементов.

Вторая функция document-ready выполняется сразу же после загрузки страницы и формирования структуры DOM. В данной функции создается интерфейс панели. Для этого к каждому элементу $("#navigation li") добавляется элемент <span></span>, после чего определяется его текст. В заключении к каждому элементу $("#navigation li") подключается обработчик события hover, который выполняет функцию смены изображения.


<script type="text/javascript">
function linkClick(link_idx) {
    var cnt = 0;
    $("#navigation li").each(function() {
        if (++cnt == link_idx) {
            var linkText = $(this).find("a").text();
            alert('linkClick : ' + linkText);
            return false;
        }
    }); 
}

$(document).ready(function() {
    // Всем элементам <li> добавляем теги <span>
    $("#navigation li").prepend("<span></span>");

    // перебор элементов <li>
    $("#navigation li").each(function() {
        // получение текста тега <li>
        var linkText = $(this).find("a").html();
        // помещение текста в тег <span>
        $(this).find("span").show().text(linkText);
    }); 

    // обработка событий входа/выхода курсора hover
    $("#navigation li").hover(function() {
        // событие входа курсора ...
        $(this).find("span").stop().animate({ 
            // переместить <span> на 40px вверх
            marginTop: "-40"
        }, 250);
    } , function() {
        // событие выхода курсора...
        $(this).find("span").stop().animate({
            // переместить <span> на свое место (0px)
            marginTop: "0"
        }, 250);
    });
});
</script>
 

Примечание : в большинстве случаев данный код выполнит свою функцию при формировании интерфейса панели и смене изображения при наведении курсора. Но вот для такой не очень насыщенной страницы как эта он не сработал. Причина была связана с тем, что у заголовка данного примера выше его реализации стоит ссылка #nav_panel, которая включается браузерами Google Chrome, Microsoft Edge, Opera (у других не проверял, полагаю и ими также) в структуру DOM первого блока <ul> и его первого элемента <li> в виде ссылки. В результате интерфейс, а вместе с ним и бизнес-логика навигационной панели исказились. Подробности описаны в особенностях.

Анимация боковой панели

Ниже представлен блок с реализацией боковой всплывающей панели, которую можно открыть нажатием на элемент-ссылку с изображением ≡. Описание примера представлено ниже.

Нажмите на ссылку ≡, чтобы открыть боковую панель.

Описание html

Ниже представлен HTML-код описания интерфейса боковой всплывающей панели, включенный в блок <div>, в котором объединены несколько ссылок. Класс "sidenav" определяет css-стиль интерфейса боковой панели : размер, цвет, прозрачность и т.д. Вызов панели осуществляется нажатием клавиши мыши на ссылку, представленную в виде изображения/символа ≡ (&equiv;). Стиль самой ссылки включен в описание, и определяет представление курсора мыши в виде указателя pointer при наведении.


<div id="div_sidenav" class="sidenav">
   <a href="javascript:void(0)" class="closebtn" 
                                onclick="">×</a>
   <a href="javascript:sideNavClick(1)">Сервис</a>
   <a href="javascript:sideNavClick(2)">Клиенты</a>
   <a href="#unit_sidenav">Контакты</a>
</div>
<p>Нажмите на ссылку &equiv;, чтобы открыть боковую панель.</p>
<div style="font-size:30px;cursor:pointer;color:blue" 
     id="sidebar" onclick="">&equiv;</div>
 

На что следует обратить внимание в данном html-коде?

  • Во-первых, описание первой ссылки в панели (в первом блоке <div>) и последней ссылки (второй блок <div>) в листинге включают опцию вызова методов onclick без значения. В принципе, в скриптах ниже представлены методы открытия и закрытия панели, которые можно включить в описание данных ссылок, и которые меняют стили без использования jQuery. В этом случае можно будет обойтиcь и без jQuery для открытия и закрытия панели.
  • Во-вторых, два пункта меню включают вызов метода sideNavClick, который определен в скриптовом блоке <script>. Третий пункт меню обновляет страницу с переходом в позицию #unit_sidenav, которая определена у заголовка данного второго примера в виде ссылки <a name="unit_sidenav" />.

На заметку : ссылка на заголовок #unit_sidenav включается браузерами Google Chrome, Microsoft Edge, Opera (на других не проверял, полагаю и ими также) в структуру DOM блока <div_sidenav> в качестве первой ссылки и должна учитываться в скриптах при выборе действия пункта меню. Если это не учитывать, то искажается бизнес-логика нажатий клавиш на ссылки (cм. описание блока скриптов <script type="text/javascript">).

Описание CSS-стилей

CSS-стили для боковой навигационной панели включены в скриптовой блок, которой размещается в теле страницы <body>. Загрузка стилей выполняется методом injectCSS, о котором уже подробно изложено выше. В описание стилей определяется размер навигационной панели, цвет фона, прозрачность, цвет ссылки при наведении и т.д. Следует обратить внимание, что нулевой размер ширины скрывает панель при открытии страницы. Положение панели по вертикали вычисляется в скриптовом блоке. Перемещением контента установите положение ссылки в верхней и в нижней части страницы. После этого откройте панель; Вы должны увидеть, что панель при открытии перемещается в сторону расположения ссылки. Это реализовано в скриптах.

<script type="text/javascript">
$(document).ready(function() {
   $.injectCSS({
      ".sidenav" : {
         'height': '150px',
         'width': '0',
         'position': 'fixed',
         'z-index': '1',
         'bottom': '0',
         'left': '0',
         'background-color': '#ee4',
         'overflow-x': 'hidden',
         'transition': '0.5s',
         'padding-top': '30px',
         'opacity': '0.9'
      },
      ".sidenav a" : {
         'padding': '8px 8px 2px 12px',
         'text-decoration': 'none',
         'font-size': '16pt',
         'color': '#4181ff',
         'display': 'block',
         'transition': '0.3s'
      },
      ".sidenav a:hover " :{
         'color': '#f141f1'
      },
      ".sidenav .closebtn " :{
         'position': 'absolute',
         'top': '0',
         'right': '6px',
         'font-size': '30px'
      }
   });
});
</script">
 

Описание js-скриптов

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

Методы openNav и closeNav, назначения которых понятно из названия, можно использовать при управлении боковой панелью. Для этого их следует включить в опции onclick html-кода. Таким образом, можно будет реализовать боковую панель без библиотеки jQuery.

Последняя функция document-ready выполняется сразу же после формирования структуры DOM, т.е. после загрузки страницы. В функции подключаются обработчики действий click к ссылкам открытия $("#sidebar") и закрытия $("#div_sidenav").find('a:first').next() панели. При открытии панели определяется положение ссылки на экране по вертикали (переменная y) и устанавливаются css-параметры панели $('#div_sidenav').css({width:'125', top:y}). При закрытии панели css-параметр width обнуляется.


function sideNavClick(idx) {
    var cnt = 0;
    $("#div_sidenav").find('a').each(function() {
        if (cnt++ == idx) {
            var linkText = $(this).text();
            console.log('sideNavClick : ' + linkText);
            return false;
        }
    }); 
    closeNav();
}

function openNav() {
    document.getElementById("div_sidenav")
            .style.width = "250px";
}

function closeNav() {
    document.getElementById("div_sidenav")
            .style.width = "0";
}

$(document).ready(function() {
  // открываем боковую панель
  $("#sidebar").click(function() {
     // Определяем позицию элемента по вертикали
     var offset_t = $(this).offset().top - 
                    $(window).scrollTop();
     var height = $(window).height();
     var y = offset_t;
     if (($('#div_sidenav').height() + offset_t) > height) {
         y = offset_t - $('#div_sidenav').height();
     }
     // Изменяем css-стили панели
     $('#div_sidenav').css({width:'125', top:y});
  });

  // боковую панель убираем с экрана
  $("#div_sidenav").find('a:first').next().click(function(){
     $('#div_sidenav').css({width:'0'});
  });
});
 

Примечание : при описании примера появилась ошибка неправильного вывода в консоль наименования ссылки. Причина была связана с тем, что у заголовка второго примера выше его реализации разместилась невидимая ссылка #unit_sidenav, которая была включена браузерами Google Chrome, Microsoft Edge, Opera (у других не проверял, полагаю и ими также) в структуру DOM блока <div> в виде ссылки. В результате метод sideNavClick стал неправильно определять нажатую ссылку. Ниже представлена корректировка кода метода sideNavClick для учета невидимой ссылки (<a name="" />) в структуре блока div.

Особенности созданной структуры DOM

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

Неприятная проблема на ровном месте. Начал изучать код и подключать отладчика в браузере. В конце концов нашел причину, которая в первом примере была связана с размещением невидимой ссылки <a name="nav_panel" /> перед заголовком примера. Эту ссылку браузеры Google Chrome, Microsoft Edge, Opera (другие не проверял, полагаю и они также) включают в структуру DOM первого блока <ul> и его первого элемента <li>.

Нужно предупредить в javascript-коде причину, чтобы следующий раз не наступить на эти грабли. Для этого в скриптовый блок внес небольшие изменения, связанные с проверкой количества дочерних ссылок ($(this).find("a").length); если две ссылки, то удаляется первая дочерняя и первая родительская (без проверки). Всё заработало как задумано.

// Цикл перебора элементов
$("#navigation li").each(function() {
    // контроль количества дочерних ссылок
    if ($(this).find("a").length == 2) {
        // удаление первой ссылки элемента
        $(this).find("a:first").remove();
        // удаление первой ссылки у родительского элемента
        $(this).parent().find("a:first").remove();
    }
    var linkText = $(this).find("a").html();
    $(this).find("span").show().text(linkText);
}); 
 

Со вторым примером было проще. Причину сразу же проверил «по образцу и подобию» первого примера в отладчике браузера. И она подтвердилась; неправильно определялись наименования в виду включения невидимой ссылки заголовка второго примера <a name="unit_sidenav" /> в структуру DOM блока <div> (id="div_sidenav"). Внес изменения в метод sideNavClick, связанные с проверкой количества ссылок; если ссылок 5, то первую удаляем. И все заработало как надо.

function sideNavClick(idx) {
    if ($("#div_sidenav").find('a').length == 5)
        $("#div_sidenav").find('a:first').remove();
    var cnt = 0;
    $("#div_sidenav").find('a').each(function() {
        if (cnt++ == idx) {
            var linkText = $(this).text();
            console.log('sideNavClick : ' + linkText);
        }
    }); 
    closeNav();
}

Примечение : при описании особенностей я разместил ссылку на прототип первого примера (см. курсивный текст выше представления панелей), закомментировал изменения в скриптах и приступил к созданию скриншота искаженного интерфейса первого примера. К моему удивлению, интерфейс анимированной панели первого примера не исказился и бизнес-логика работала корректно. Получилось, что клин был выбит клином, т.е. размещение второй видимой ссылки обеспечил корректное формирование структуры DOM. Осадок остался : невидимая ссылка может привести к искажению интерфейса и бизнес-логики. Я не пишу, что это ошибка браузера при формировании структуры DOM, поскольку это прослеживается сразу в нескольких браузерах. Может быть это так задумано. Но с точки зрения программиста об этой особенности необходимо помнить.

Связанные страницы

Описание библиотеки jQuery
Выбор элементов из объектной модели документа DOM
Базовая анимация библиотекой jQuery
Фильтрация наборов и поиск элементов jQuery методами filter, find
  Рейтинг@Mail.ru