[Из песочницы] Создаем свое Amazon-like навигационное меню

Ранее на Хабре уже рассказывали о загадочном меню. Изобретение по истине гениальное и полезное. Уверен, каждый из вас хотел бы модифицировать меню на своем сайте таким же образом.image

Как же это сделать? Предполагается, что у вас на сайте подключен jQuery. Если нет — можете переработать скрипт под чистый JS. На Github уже есть готовый плагин для этого, написанный Бен Кэменсом. Но мне он показался слишком громоздким и не слишком подходящим для текущего меню. Поэтому было принято решение писать свой скрипт.Сразу могу сказать, что это не изобретение велосипеда, а скорее краткое руководство по созданию амазон-меню. Далее более подробная информация о поставленной задаче и ее решении:

Итак, имеется меню с фиксированной шириной:

image

Это существенно упрощает задачу. Для каждого положения курсора вычисляется треугольник с вершинами в верхнем и нижних углах списка и курсоре. Если курсор попадает на область другого элемента в голубом треугольнике, уже открытое подменю сменится, но с задержкой, которая даст пользователю возможность протащить курсор в область подменю. Далее используем известные координаты. А именно: нижние вершины. Все, что нам нужно вычислить — это текущее положение курсора. Кроме того, нужно запомнить предыдущее значение положения курсора. На этом хватит теории, дальше — больше практики.

Как было раньше Верстка меню:

Обработчик для меню:

$(».menu-all > ul > li»).hover (function (){ $(this).addClass («active»).find («div.dropdown-menu-main»).show (); $(»#over-hidden»).addClass («over»); }, function (){ $(this).removeClass («active»).find («div.dropdown-menu-main»).hide (); $(»#over-hidden»).removeClass («over»); }); В итоге получается: image

Ок, исправляем ситуацию.

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

// Присваиваем координаты для предыдущей позиции курсора var x2 = 0; var y2 = 0;

// Известные координаты нижних углов треугольника var x1 = 0; var y1 = 70; var x3 = 900; var y3 = 70;

// Присваиваем зничение вспомогательной переменной var in_delta = false;

// При наведении на меню так же присваиваем ей false $('.dropdown-menu-main').mouseenter (function () { in_delta = false; });

// Ну и теперь самое главное событие $('.menu-all > ul > li').mousemove (function (e) { var parentOffset = $(this).parent ().offset ();

// Берем текущие координаты курсора var x0 = e.pageX — parentOffset.left; var y0 = e.pageY — parentOffset.top;

// Ну и теперь простая формула для определения находится ли курсор в треугольнике var z1 = (x1 — x0) * (y2 — y1) — (x2 — x1) * (y1 — y0); var z2 = (x2 — x0) * (y3 — y2) — (x3 — x2) * (y2 — y0); var z3 = (x3 — x0) * (y1 — y3) — (x1 — x3) * (y3 — y0); if ((z1 > 0 && z2 > 0 && z3 > 0) || (z1 < 0 && z2 < 0 && z3 < 0)) { in_delta = true; } else { // Здесь непосредственно нужный нам код для показа меню $('.menu-all > ul > li.active').removeClass ('active').find («div.dropdown-menu-main»).hide (); $(this).addClass («active»).find («div.dropdown-menu-main»).show (); $(»#over-hidden»).addClass («over»);

// И сразу же присваиваем значение нашей переменной in_delta = false; }

// Ну и обязательно присваиваем значения координатам для «предыдущего значения положения» для следущего события x2 = e.pageX — parentOffset.left; y2 = e.pageY — parentOffset.top; }).mouseleave (function () { if (! in_delta) { // Здесь код для скрытия меню $(this).removeClass («active»).find («div.dropdown-menu-main»).hide (); $(»#over-hidden»).removeClass («over»); } }); Вот и все.

Удачи при воспроизведении!

© Habrahabr.ru