这是一个js实现京东无延迟菜单效果,感觉很好,分享给大家...
先来理清思路:
1.开发基本的菜单结构
2.开发普通的二级菜单效果
3.假如延迟解决移动问题,切换子菜单时候,用setTimeout设置延迟
debounce去抖技,在事件被频繁触发是,只执行一次处理
4.解决延迟引入的新问题
跟踪鼠标的移动,用鼠标当前位置,和鼠标上一次位置与子菜单上下边缘的三角形区域进行比较
运用到向量
二位向量叉乘公式
用叉乘法判断点在三角形内
最终效果:鼠标自然的移动和点击到子菜单
切换时无延迟
下面开始代码:
开发基本的菜单结构
京东菜单无刷新 .wrap{ position:relative; width:200px; left:50px; top:50px; } ul{ padding:15px; 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 rgba(0,0,0,.3); left: 200px; top:0; box-sizing:border-box; margin: 0px; padding:10px; } .sub-content a{ font-style:12px; color:#666; text-decoration:none; } .sub-content dd a{ border-left:1px solid #e0e0e0; padding:0 1px; 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; }
- 家用电器
- 手机 / 运营商 / 数码
- 电脑办公 / 办公
- 家居 / 家具 / 家装 / 厨具
- 男装 / 女装 / 童装 / 内衣
- 美妆个护 / 宠物
- 女鞋 / 箱包 / 钟表 / 珠宝
- 男鞋 / 运动 / 户外
- 汽车 / 汽车用品
- 电视>
- 曲面电视 超薄电视 HDR电视 DLED电视
- 空调>
- 挂壁式空调 柜式空调 中央空调 以旧换新
- 洗衣机>
- 滚筒式洗衣机 洗烘一体机 波轮洗衣机 迷你洗衣机
- 手机通讯>
- 手机 对讲机 以旧换新 手机维修
- 运营商>
- 合约机 选号机 固定电话 办宽带
- 手机配件>
- 手机壳 贴膜 手机存储卡 数据线
- 电脑整机>
- 笔记本 游戏本 平板电脑
- 电脑配件>
- 显示器 CPU 主板
- 外设产品>
- 鼠标 键盘 键盘套餐
- 厨具>
- 烹饪锅具 刀剪配件 厨房配件 水具酒具
- 家纺>
- 床品套件 被子 枕芯 蚊帐
- 生活日用>
- 收纳用品 雨伞雨具 净化除味 浴室用品
- 女装>
- 商城同款 当季热卖 2017新品 连衣裙
- 男装>
- 商城同款 当季热卖 2017新品 牛仔裤
- 面部护肤>
- 补水保湿 卸妆 洁面
解决第2、3个问题
$(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('acrive')
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')
}
})
})
解决延迟引入的新问题
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){
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){
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)
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。



