<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script> <style> .wrap { position: relative; width: 200px; left: 50px; top: 50px; background: #6c6669; padding: 15px 0; } ul { list-style: none; margin: 0; padding: 0; color: #fff; border-right-width: 0; } li { height: 40px; line-height: 40px; padding-left: 12px; cursor: pointer; font-size: 14px; position: relative; } li.active { background: #999395; } li span:hover { color: #c81623; } .none { display: none; } #sub { width: 600px; min-height: 270px; position: absolute; border: 1px solid #f7f7f7; background: #f7f7f7; box-shadow: 2px 0 5px rgba(0, 0, 0, 0.3); left: 200px; top: 0; box-sizing: border-box; margin: 0; padding: 10px; } .sub_content a { text-decoration: none; color: #666; font-size: 12px; } .sub_content dd a { border-left: 1px solid #e0e0e0; padding: 0 10px; margin: 4px 0; } .sub_content dl { overflow: hidden; } .sub_content dt { float: left; width: 70px; clear: left; font-weight: bold; position: relative; } .sub_content dd { float: left; margin-left: 5px; border-top: 1px solid #eee; margin-bottom: 5px; } </style> </head> <body> <div class="wrap" id="wrap"> <ul> <li data-id="a"> <span> 一级导航1 </span> </li> <li data-id="b"> <span> 一级导航2 </span> </li> <li data-id="c"> <span> 一级导航3 </span> </li> <li data-id="d"> <span> 一级导航4 </span> </li> <li data-id="e"> <span> 一级导航5 </span> </li> <li data-id="f"> <span> 一级导航6 </span> </li> </ul> <div id="sub" class="none"> <div id="a" class="sub_content none"> <dl> <dt> <a href="#"> 二级菜单1 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单1 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单1 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> </div> <div id="b" class="sub_content none"> <dl> <dt> <a href="#"> 二级菜单2 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单2 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单2 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单2 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单2 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单2 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> </div> <div id="c" class="sub_content none"> <dl> <dt> <a href="#"> 二级菜单3 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单3 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单3 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> </div> <div id="d" class="sub_content none"> <dl> <dt> <a href="#"> 二级菜单4 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单4 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单4 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单4 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> </div> <div id="e" class="sub_content none"> <dl> <dt> <a href="#"> 二级菜单5 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单5 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> </div> <div id="f" class="sub_content none"> <dl> <dt> <a href="#"> 二级菜单6 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单6 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单6 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单6 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> <dl> <dt> <a href="#"> 二级菜单6 </a> </dt> <dd> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> <a href="#"> 三级菜单 </a> </dd> </dl> </div> </div> </div> </body> <script> $(document).ready(function() { var sub = $("#sub"); var activeRow, // 已激活的一级菜单 activeMenu; // 已激活的子级菜单 var timer; // 鼠标是否在子菜单里 var mouseInSub = false; sub.on("mouseenter", function() { mouseInSub = true; }) .on("mouseleave", function() { mouseInSub = false; }); // 记录鼠标的位置 var mouseTrack = []; var moveHandler = function(e) { mouseTrack.push({ x: e.pageX, y: e.pageY }); // 只需要当前点和上一个点 if (mouseTrack.length > 3) { mouseTrack.shift(); } }; // 此处只能给整个菜单注册,而非只给一级菜单加,否则timer中的回调执行时,activeRow已为空 $("#wrap").on("mouseenter", function() { sub.removeClass("none"); $(document).bind("mousemove", moveHandler);// 用于记录鼠标位置 }) .on("mouseleave", function() { sub.addClass("none"); if (activeRow) { activeRow.removeClass("active"); activeRow = null; } if (activeMenu) { activeMenu.addClass("none"); activeMenu = null; } $(document).unbind("mousemove", moveHandler); // 注意解绑,以免影响其他组件 }) .on("mouseenter", "li", function(e) { if (!activeRow) { active(e.target); return; } if (timer) { clearTimeout(timer); } var curMouse = mouseTrack[mouseTrack.length - 1]; // 鼠标当前坐标 var prevMouse = mouseTrack[mouseTrack.length - 2]; // 鼠标上一次坐标 // console.log(curMouse, prevMouse); var delay = needDelay(sub, curMouse, prevMouse); if (delay) { // 加入延迟器,解决斜方移动切换,只能折线移动的问题 timer = setTimeout(function() { if (mouseInSub) { return; } activeRow.removeClass("active"); activeMenu.addClass("none"); active(e.target); timer = null; }, 300); } else { activeRow.removeClass("active"); activeMenu.addClass("none"); active(e.target); } }); function active(target) { activeRow = $(target); activeRow.addClass("active"); activeMenu = $("#" + activeRow.data("id")); activeMenu.removeClass("none"); } }); // 向量是终点坐标减去起点坐标 function vector(a, b) { return { x: b.x - a.x, y: b.y - a.y }; } // 向量的叉乘 function vectorPro(v1, v2) { return v1.x * v2.y - v1.y * v2.x; } // 用位运算高效判断符号相同 function sameSign(a, b) { return (a ^ b) >= 0; } // 判断点是否在三角形内 function isPointInTranjgle(p, a, b, c) { var pa = vector(p, a); var pb = vector(p, b); var pc = vector(p, c); var t1 = vectorPro(pa, pb); var t2 = vectorPro(pb, pc); var t3 = vectorPro(pc, pa); return sameSign(t1, t2) && sameSign(t2, t3); } // 是否需要延迟 function needDelay(ele, curMouse, prevMouse) { if (!curMouse || !prevMouse) { return; } var offset = ele.offset(); // 左上点 var topleft = { x: offset.left, y: offset.top }; // 左下点 var leftbottom = { x: offset.left, y: offset.top + ele.height() }; return isPointInTranjgle(curMouse, prevMouse, topleft, leftbottom); } </script> </html>