前记
演示效果
重点
1、页面布局及CSS知识
2、如何实现无延迟加载
所需框架
Jquery
实现笔记
html
左半边的一级菜单,布局使用ul和li标签,代码片段:
<ul>
<li data-id="a">
<span>家用电器</span>
</li>
…………
<li data-id="j">
<span> 手机 / 运用商 / 数码 </span>
</li>
</ul>
说明:
(1)ul是无序列表,li标签定义列表的内容,自带·的样式,它们都是块级元素
(2)data-*是自定义数据,用于存储页面或应用程序的私有自定义数据,赋予我们在所有 HTML 元素上嵌入自定义 data 属性的能力
右边二级菜单的html结构
首先使用div作为父级容器,然后在用若干个div表示每一个一级菜单所对应的二级菜单。
在每一个二级菜单div中,使用了dl、dt、dd元素作为布局的标签,实例代码部分如下:
<div id="sub" class="none">
<div id="a" class="sub_content none">
<dl>
<dt>
<a href="#">电视1<i>></i></a>
</dt>
<dd>
<a href="#">合资品牌</a>
<a href="#">国产品牌</a>
<a href="#">互联网品牌</a>
</dd>
</dl>
说明:
(1)dl 标签定义了定义列表(definition list)
(2)dl 标签用于结合 dt (定义列表中的项目)和 dd (描述列表中的项目)。
CSS样式
这部分需要记录的是一级菜单鼠标移上去时的高亮效果
li.active{
background: #999395;
}
li span:hover{
color: #c81623;
}
更多具体的样式可以参考源码
JS 代码
具体的代码详解参考代码中的注释:
$(document).ready(function () {
var sub = $('#sub') //二级菜单的父div
var activeRow
var activeMenu
//优化
var timer
var mouseInSub = false
var mouseTrack=[]
var moveHandler=function(e){
mouseTrack.push({
x:e.pageX,
y:e.pageY
})
if(mouseTrack.length>3){
mouseTrack.shift()
}
}
sub.on('mouseenter', function (e) {
//当鼠标放在二级菜单上是,标志位设为true
mouseInSub = true
}).on('mouseleave', function (e) {
//同上离开时设置为false
mouseInSub = false
})
//id test为整个一二级菜单的父容器div
$('#test').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)
console.log('mouse leave bind handler')
})
$('#test') //鼠标进入菜单时,注册鼠标移动时的回调事件
.on('mouseenter',function(e){
$(document).bind('mousemove',moveHandler)
console.log('mouse enter bind handler')
})
$('#test li').on('mouseenter',function (e) {
sub.removeClass('none')
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){
console.log("delay")
timer = setTimeout(function () {
if (mouseInSub) {
console.log("----")
return
}
activeRow.removeClass('active')
activeMenu.addClass('none')
activeRow = $(e.target)
activeRow.addClass('active')
activeMenu = $('#' + activeRow.data('id'))
activeMenu.removeClass('none')
timer = null
}, 500)
}else{
console.log(" no delay")
var prevActiveRow=activeRow
var prevActiveMenu=activeMenu
activeRow=$(e.target)
activeMenu=$('#'+activeRow.data('id'))
prevActiveMenu.addClass('none')
prevActiveRow.removeClass('active')
activeRow.addClass('active')
activeMenu.removeClass('none')
}
})
})
说明:
(1)三角形的图如下所示:
1.png
(2)有关向量判断的方法都封装在了函数function.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 sameSign(a,b){
return (a^b)>=0
}
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,curMousePos){
var offset =elem.offset()
var topLeft={
x:offset.left,
y:offset.top
}
var bottomLeft={
x:offset.left+elem.width(),
y:offset.top+elem.height()
}
return isPointInTrangle(curMousePos,leftCorner,topLeft,bottomLeft)
}
本实例是慕课网上的一个课程,有兴趣的小伙伴可以去看看~
结束:附上源码 码云:JS实现京东无延迟菜单效果
微信公众号若有疑问可以QQ联系笔者,虽然不一定100%解决你的问题,但是可以交流探讨一波:2276604211
顺便打个内推广告:如果有想入职中国银联上海技术开发的童鞋,也可以加上面的QQ资讯,笔者可以帮你回答一些相关问题~~
网友评论