jquery+css实现商城分类导航菜单功能
发现公司多个网站(制信网、优制网等)首页的分类导航菜单有一个非常小的bug:当鼠标想从一级菜单移动到自己的下属二级菜单时,如果鼠标在移动过程中经过了其他的一级菜单区域,那么被经过的一级菜单马上会弹出属于自己的二级菜单,导致不能选中原本一级菜单下的二级菜单项,这bug其实一般不太影响使用,不过有时候还是会影响使用体验,前几天利用空闲时间,查了网上的资料,写了一简单的demo,解决了这个问题,下面把代码贴出来,html代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style>
.wrap{
position: relative;
width: 200px;
left: 50px;
top:50px;
}
ul{
padding: 15px,0;
margin: 9;
list-style: none;
background: #6c6669;
color:#FFFFFF;
border-right-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 id="test" class="wrap">
<ul>
<li data-id="a"><span>家用电器</span></li>
<li data-id="b"><span>手机 / 运营商 / 数码</span></li>
<li data-id="c"><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>
<a href="#">互联网品牌</a>
</dd>
</dl>
<dl>
<dt>
<a href="#">冰箱<i>></i></a>
</dt>
<dd>
<a href="#">合资品牌</a>
<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>
<a href="#">互联网品牌</a>
</dd>
</dl>
<dl>
<dt>
<a href="#">空调<i>></i></a>
</dt>
<dd>
<a href="#">合资品牌</a>
<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>
<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>
<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>
<a href="#">互联网品牌</a>
</dd>
</dl>
</div>
</div>
</div>
<script src="js/jquery.min.js"></script>
<script src="js/triangle.js"></script>
<script src="js/menudropdown.js"></script>
</body>
</html>
js:menudropdown.js 代码:
js:menudropdown.js 代码:
$(document).ready(function(){
var sub=$('#sub');
var activeRow
var activeMenu
var timer
var mouseInSub=false
sub.on('mouseenter',function(e){
mouseInSub=true
}).on('mouseleave',function(e){
mouseInSub=false
})
var mouseTrack=[];
var moveHandler=function(e){
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)
})
.on('mouseleave',function(e){
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){
activeRow=$(e.target).addClass('active');
activeMenu=$('#'+activeRow.data('id'));
activeMenu.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)
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')
}
})
})
triangle.js代码: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){
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(t1,t3)
}
function samesign(a,b){
return (a^b)>=0
}
function needDelay(elem,leftCorner,currMousePos){
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);
}