Ранее на Хабре уже рассказывали о загадочном меню. Изобретение по истине гениальное и полезное. Уверен, каждый из вас хотел бы модифицировать меню на своем сайте таким же образом.
Как же это сделать?
Предполагается, что у вас на сайте подключен jQuery. Если нет — можете переработать скрипт под чистый JS. На Github уже есть готовый плагин для этого, написанный Бен Кэменсом. Но мне он показался слишком громоздким и не слишком подходящим для текущего меню. Поэтому было принято решение писать свой скрипт.
Сразу могу сказать, что это не изобретение велосипеда, а скорее краткое руководство по созданию амазон-меню. Далее более подробная информация о поставленной задаче и ее решении:
Итак, имеется меню с фиксированной шириной:
Это существенно упрощает задачу. Для каждого положения курсора вычисляется треугольник с вершинами в верхнем и нижних углах списка и курсоре. Если курсор попадает на область другого элемента в голубом треугольнике, уже открытое подменю сменится, но с задержкой, которая даст пользователю возможность протащить курсор в область подменю. Далее используем известные координаты. А именно: нижние вершины. Все, что нам нужно вычислить — это текущее положение курсора. Кроме того, нужно запомнить предыдущее значение положения курсора. На этом хватит теории, дальше — больше практики.
Как было раньше
Верстка меню:
<div class="menu-all"> <ul> <li><a>Caption</a> <div class="dropdown-menu-main">some content</div> </li> <li><a>Caption 2</a> <div class="dropdown-menu-main">some content 2</div> </li> </ul> </div>
Обработчик для меню:
$(".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"); });
В итоге получается:
Ок, исправляем ситуацию.
Верстка, естественно остается той же, да бы не привлекать верстальщиков. Просто модифицируем обработчик:
// Присваиваем координаты для предыдущей позиции курсора 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"); } });
Вот и все.
Удачи при воспроизведении!
ссылка на оригинал статьи http://habrahabr.ru/post/252975/
Добавить комментарий