$(document).ready(function () {
var sub = $('#sub');
var row; //每个<li>
var menu; //二级菜单
var timer;
var mouseInsub = false; //鼠标是否进入到二级菜单的一个flag
var mouseTrack = [];
var moveHandler = function (e) {
mouseTrack.push({ //插入鼠于当前页面的坐标
x: e.pageX,
y: e.pageY
});
if(mouseTrack.length > 3){ //数组中只需要保存当前位置和上一次的位置
mouseTrack.shift();
}
};
//检查鼠标是否移入到二级菜单,如果移到了二级菜单,则下面定时器直接返回
sub.on("mouseenter",function () {
mouseInsub = true;
}).on("mouseleave",function () {
mouseInsub = false;
});
$("#test")
.on("mouseenter",function (e) { //mouseover移入子元素会触发mouseout,这个不会
sub.removeClass("none");
//常识,mousemove绑定在document上,鼠标在div上移动触发该事件,移出时记得清除
$(document).bind("mousemove",moveHandler);
})
.on("mouseleave",function (e) {
sub.addClass("none");
if(row){
row.removeClass("active");
row = null;
}
if(menu){
menu.addClass("none");
menu = null;
}
$(document).unbind("mousemove",moveHandler);
})
.on("mouseenter","li",function (e) { //只在$("#test")下的“li”才触发
if(!row){
row = $(e.target).addClass("active"); //e.target当前指向的真正元素
menu = $("#" + row.data("id"));
menu.removeClass("none");
return;
}
if(timer){
clearTimeout(timer);
}
var currMousePos = mouseTrack[mouseTrack.length - 1]; //鼠标当前坐标
var leftCorner = mouseTrack[mouseTrack.length - 2]; //上次鼠标的坐标
var delay = needDelay(sub, leftCorner, currMousePos);
console.log(currMousePos, leftCorner,delay);
if(delay){ //如果在三角形内,这需要延迟
timer = setTimeout(function () { //防止鼠标打斜进入二级菜单
if(mouseInsub){ //鼠标在二级菜单里的话
return;
}
row.removeClass("active"); //得写在下面,写在上面row未定义报错
menu.addClass("none");
row = $(e.target).addClass("active");
menu = $("#" + row.data("id")); //data-xx属性都可以这样,如data-id
menu.removeClass("none");
}
,300);
}else{
row.removeClass("active"); //移除上一任样式
menu.addClass("none");
row = $(e.target).addClass("active"); //给当前所指li添加样式
menu = $("#" + row.data("id"));
menu.removeClass("none");
}
})
});
function isSameSign(a,b) {
return (a ^ b) >= 0;
//a异或b大于等于则认为符合相同
//最高位的异或运算,不相同返回1
}
function vector(a,b) { //向量
var a = a || {};
var b = b || {};
return{ //终点坐标 - 起点坐标
x: b.x - a.x,
y: b.y - a.y
};
}
function vectorProduct(v1,v2) { //向量X乘公式
return v1.x * v2.y - v1.y * v2.x;
//向量1的x坐标 * 向量2的y坐标 - 向量1的y坐标 * 向量2的x坐标
}
function isPointInTrangle(p,a,b,c) {
var pa = vector(p, a);
var pb = vector(p. b);
var pc = vector(p, c);
var t1 = vectorProduct(pa, pb); //返回向量X乘结果
var t2 = vectorProduct(pb, pc);
var t3 = vectorProduct(pc, pa);
return isSameSign(t1,t2) && isSameSign(t2,t3);
}
function needDelay(elem,leftCorner,currMousePos) {
if (!currMousePos || !leftCorner) {
return;
}
var offset = elem.offset(); //jquery的offset()方法获取二级菜单上下边缘的坐标
var topLeft = { //左上角坐标
x: offset.left,
y: offset.top
};
var bottomLeft = { //左下角坐标
x: offset.left,
y: offset.top + elem.height()
};
return isPointInTrangle(currMousePos, leftCorner, topLeft, bottomLeft);
}