如果鼠标移出菜单栏,然后再进去时,显示就会不正确了,是不是因为var leftCorner=mouseTrack[mouseTrack.length-2];计算会出错。
代码如下:
<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
//二进制的正负表示是在最高位,1表示负,0表示正,抑或运算是仅当对应的2位有一位为1时才返回1,反过来如果抑或运算返回的结果是0(正),则一定是2个1,或者2个0.反之,则是一个0,一个1
function sameSign(a,b){
return (a^b)>=0;
}
//向量的定义
function vector(a,b){
return {
x:b.x-a.x,//终点的坐标减去起点的坐标
y:b.y-a.y
}
}
//向量叉乘公式
function vectorProduct(v1,v2){
return v1.x*v2.y-v2.x*v1.y
}
//叉乘判断方法
function isPointInTrangle(p,a,b,c){//p:鼠标当前点的坐标,a:鼠标上一次的坐标,b,c:二级菜单上下边缘坐标
var pa=vector(p,a);
var pb=vector(p,b);
var pc=vector(p,c);
var t1=vectorProduct(pa,pb);
var t2=vectorProduct(pb,pc);
var t3=vectorProduct(pc,pa);
return sameSign(t1,t2)&&sameSign(t2,t3);
}
function needDelay(elem,leftCorner,currMousePos){//用offset方法获取上下边缘
var offset=elem.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)
}
</script>
<script>
$(function(){
var sub=$('#sub');
var activeRow;//选中的行
var activeMenu;//选中的行对应的二级菜单
var timer;//setTimeout返回的计时器id
var mouseInSub=false;//当前鼠标是否在子菜单里
sub.on('mouseenter',function(e){
mouseInSub=true;
}).on('mouseleave',function(e){
mouseInSub=false;
});
//创建数组,记录
var mouseTrack=[];//数组跟踪记录鼠标的位置
var moveHandler=function(e){//鼠标离开菜单时,需要对绑定在document上的mousemove事件解绑,以免影响页面中其他组件,所以将事件监听函数独立出来,方便后续解绑操作
mouseTrack.push({
x:e.pageX,
y:e.pageY
});
if(mouseTrack.length>3){
mouseTrack.shift();
}
};
$('#test')
.on('mouseenter',function(e){
//sub.removeClass('none');
$(document).bind('mousemove',moveHandler);//mousemove事件一般绑定在document上
})
.on('mouseleave',function(e){
sub.addClass('none');//鼠标移动到一级菜单时,二级菜单隐藏
if(activeRow){//鼠标离开一级菜单,如果存在激活的行,样式要去掉,并把变量置空
activeRow.removeClass('active');
activeRow=null;
}
if(activeMenu){
activeMenu.addClass('none');
activeMenu=null;
}
$(document).unbind('mouseove',moveHandler);
})
.on('mouseenter','li',function(e){//一级菜单的列表项绑定事件
sub.removeClass('none');//鼠标移动到一级菜单时,二级菜单显示
if(!activeRow){//移过去没有激活的一级菜单
activeRow=$(e.target);
activeRow.addClass('active');
activeMenu=$('#'+activeRow.data('id'));
activeMenu.removeClass('none');
return;
}
//debounce:mouseenter频繁触发时,只执行最后一次
if(timer){
clearTimeout(timer);
}
console.log(mouseTrack)
var currMousePos=mouseTrack[mouseTrack.length-1];
var leftCorner=mouseTrack[mouseTrack.length-2];
var delay=needDelay(sub,leftCorner,currMousePos);//是否需要延迟
if(delay){//如果在三角形内,需要延迟
timer=setTimeout(function(){
if(mouseInSub){
return;
}
activeRow.removeClass('active');
activeMenu.addClass('none');
activeRow=$(e.target);
activeRow.addClass('active');
activeMenu=$('#'+activeRow.data('id'));
activeMenu.removeClass('none');
timer=null;//事件触发时,如果计时器并没有执行,就把它清掉,这样能保证事件触发停止时,会执行最后一次,而其他的都会被忽略
},300);
}else{
var prevActiveRow=activeRow;
var prevActiveMenu=activeMenu;
activeRow=$(e.target);
activeMenu=$('#'+activeRow.data('id'));
prevActiveRow.removeClass('active');
prevActiveMenu.addClass('none');//上一次二级菜单隐藏
activeRow.addClass('active');
activeMenu.removeClass('none');//上一次二级菜单显示
}
});
});
</script>你好, 你90行的代码有问题,mousemove
不会报错么
非常感谢哦。。我正好非常懒得写。。复制粘贴了。我真的非常懒啊啊啊啊啊啊啊啊啊
border-right-width !=== border-raight-width
css 第十四行
html和css代码:
<style>
.wrap{
position:relative;
width:200px;
left:50px;
top:50px;
}
ul{
padding:15px 0;
margin:9px;
list-style:none;
background:#6c6669;
color:#fff;
border-raight-width:0;
}
li{
display:block;
height:30px;
line-height:30px;
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;
position:absolute;
border:1px solid #f7f7f7;
background:#f7f7f7;
box-shadow:2px 0 5px rgba(0,0,0,.3);
left:200px;
top:0;
box-sizing:border-box;
margin:0;
padding:10px;
}
.sub_content a{
font-size:12px;
color:#666;
text-decoration:none;
}
.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;
font-weight:bold;
clear:left;
position:relative;
}
.sub_content dd{
float:left;
margin-left:5px;
border-top:1px solid #eee;
margin-bottom:5px;
}
.sub_content dt i{
width:4px;
height:14px;
font:400 9px/14px consolas;
position:absolute;
right:5px;
top:5px;
}
</style>
</head>
<body>
<div class="wrap" id="test">
<ul>
<li data-id="a">
<span>家用电器</span>
</li>
<li data-id="b">
<span>家用电器</span>
</li>
<li data-id="c">
<span>家用电器</span>
</li>
<li data-id="d">
<span>家用电器</span>
</li>
<li data-id="e">
<span>家用电器</span>
</li>
</ul>
<div id="sub" class="none">
<div id="a" class="sub_content none">
<dl>
<dt>
<a href="#">电视<i>></i></a>
</dt>
<dd>
<a href="#">合资品牌</a>
<a href="#">国产品牌</a>
<a href="#">互联网品牌</a>
</dd>
</dl>
<dl>
<dt>
<a href="#">电视<i>></i></a>
</dt>
<dd>
<a href="#">合资品牌</a>
<a href="#">国产品牌</a>
<a href="#">互联网品牌</a>
</dd>
<dd>
<a href="#">合资品牌</a>
<a href="#">国产品牌</a>
<a href="#">互联网品牌</a>
</dd>
</dl>
</div>
<div id="b" class="sub_content none">
<dl>
<dt>
<a href="#">电视<i>></i></a>
</dt>
<dd>
<a href="#">合资品牌</a>
<a href="#">国产品牌</a>
<a href="#">互联网品牌</a>
</dd>
</dl>
</div>
<div id="c" class="sub_content none">
<dl>
<dt>
<a href="#">电视<i>></i></a>
</dt>
<dd>
<a href="#">合资品牌</a>
<a href="#">国产品牌</a>
<a href="#">互联网品牌</a>
</dd>
<dd>
<a href="#">合资品牌</a>
<a href="#">国产品牌</a>
<a href="#">互联网品牌</a>
</dd>
</dl>
</div>
<div id="d" class="sub_content none">
<dl>
<dt>
<a href="#">电视<i>></i></a>
</dt>
<dd>
<a href="#">合资品牌</a>
<a href="#">国产品牌</a>
<a href="#">互联网品牌</a>
</dd>
<dd>
<a href="#">合资品牌</a>
<a href="#">国产品牌</a>
<a href="#">互联网品牌</a>
</dd>
</dl>
</div>
<div id="e" class="sub_content none">
<dl>
<dt>
<a href="#">电视<i>></i></a>
</dt>
<dd>
<a href="#">合资品牌</a>
<a href="#">合资品牌</a>
<a href="#">国产品牌</a>
<a href="#">互联网品牌</a>
</dd>
<dd>
<a href="#">合资品牌</a>
<a href="#">国产品牌</a>
<a href="#">互联网品牌</a>
<a href="#">互联网品牌</a>
<a href="#">互联网品牌</a>
</dd>
</dl>
</div>
</div>
</div>