$(document).ready(function?()?{
????var?sub?=?$('#sub');
????var?row;???//每個<li>
????var?menu;??//二級菜單
????var?timer;
????var?mouseInsub?=?false;??//鼠標(biāo)是否進入到二級菜單的一個flag
????var?mouseTrack?=?[];
????var?moveHandler?=?function?(e)?{
??????mouseTrack.push({?????//插入鼠于當(dāng)前頁面的坐標(biāo)
??????????x:?e.pageX,
??????????y:?e.pageY
??????});
??????if(mouseTrack.length?>?3){?????//數(shù)組中只需要保存當(dāng)前位置和上一次的位置
??????????mouseTrack.shift();
??????}
????};
????//檢查鼠標(biāo)是否移入到二級菜單,如果移到了二級菜單,則下面定時器直接返回
????sub.on("mouseenter",function?()?{
????????mouseInsub?=?true;
????}).on("mouseleave",function?()?{
????????mouseInsub?=?false;
????});
????$("#test")
????????.on("mouseenter",function?(e)?{??//mouseover移入子元素會觸發(fā)mouseout,這個不會
????????????sub.removeClass("none");
????????????//常識,mousemove綁定在document上,鼠標(biāo)在div上移動觸發(fā)該事件,移出時記得清除
????????????$(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")下的“l(fā)i”才觸發(fā)
????????????if(!row){
????????????????row?=?$(e.target).addClass("active");?//e.target當(dāng)前指向的真正元素
????????????????menu?=?$("#"?+?row.data("id"));
????????????????menu.removeClass("none");
????????????????return;
????????????}
????????????if(timer){??
????????????????clearTimeout(timer);
????????????}
????????????var?currMousePos?=?mouseTrack[mouseTrack.length?-?1];?//鼠標(biāo)當(dāng)前坐標(biāo)
????????????var?leftCorner?=?mouseTrack[mouseTrack.length?-?2];????//上次鼠標(biāo)的坐標(biāo)
????????????var?delay?=?needDelay(sub,?leftCorner,?currMousePos);
????????????console.log(currMousePos,?leftCorner,delay);
????????????if(delay){??//如果在三角形內(nèi),這需要延遲
????????????????timer?=?setTimeout(function?()?{?//防止鼠標(biāo)打斜進入二級菜單
????????????????????????if(mouseInsub){?//鼠標(biāo)在二級菜單里的話
????????????????????????????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");?//給當(dāng)前所指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{?????//終點坐標(biāo)?-?起點坐標(biāo)
????????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坐標(biāo)?*?向量2的y坐標(biāo)??-??向量1的y坐標(biāo)?*?向量2的x坐標(biāo)
}
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乘結(jié)果
????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()方法獲取二級菜單上下邊緣的坐標(biāo)
????var?topLeft?=?{??//左上角坐標(biāo)
????????x:?offset.left,
????????y:?offset.top
????};
????var?bottomLeft?=?{?//左下角坐標(biāo)
????????x:?offset.left,
????????y:?offset.top??+?elem.height()
????};
????
????return?isPointInTrangle(currMousePos,?leftCorner,?topLeft,?bottomLeft);
}
2018-08-16
跟老師的代碼一樣的吧