当鼠标指向div,但并没有指向li时,为什么会出现这种白框?
js代码:
/** Created by sofiaZ on 17/7/22.*/ $(document).ready(function(){ //ready事件,当DOM加载完毕且页面完全加载时发生。把所有jjQuery事件和函数置于该事件比较好。 var sub =$('#sub');//申明一个变量指向子菜单,这是直接转成 var activeRow; //申明一个变量,指向当前激活的以及菜单的行 var activeMenu; //二级菜单 //没赋初值时为false 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({ //push()方法向数组的末尾添加一个或多个元素,返回值为新数组的长度 x: e.pageX, y: e.pageY //鼠标指针的位置,x相对于文档左边缘,y相对于文档上边缘 }); if (mouseTrack.length > 3) { mouseTrack.shift(); //shift事件把数组的第一个元素删除,返回第一个元素的值。这里只想要当前以及上一次的坐标,因此保留三个就够了 } }; $('#test') .on('mouseenter',function(e) { //on事件,向元素添加事件处理程序 sub.removeClass('none'); //鼠标移动到元素时,出现二级菜单 $(document).bind('mousemove', moveHandler); } ) //document对象对应整个html文档,$(document)是对document的jquery操作,bind为元素添加事件(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('mousemove',moveHandler); //当鼠标离开菜单栏时,对mousemove事件进行解绑,以免影响页面其他事件 }) .on('mouseenter','li',function(e){ if (!activeRow){ activeRow = $(e.target); activeRow.addClass('active'); activeMenu = $('#' + activeRow.data('id')); activeMenu.removeClass('none'); return; } if (timer) { clearTimeout(timer); } //当事件还没触发时,清掉计时器,这样可以保证事件只触发最后一次的?(debounce去抖技术基本原理?) var currMousePos = mouseTrack[mouseTrack.length - 1]; //当前鼠标坐标 var leftCorner = mouseTrack[mouseTrack.length - 2]; //上一次鼠标坐标 var delay = needDelay(sub, leftCorner, currMousePos); if (delay) { timer = setTimeout(function(){ //setTimeout返回值是一个ID? if (mouseInsub) { return; } activeRow.removeClass('active'); activeMenu.addClass('none'); activeRow = $(e.target); activeRow.addClass('active'); activeMenu = $('#' + activeRow.data('id')); activeMenu.removeClass('none'); //大概就是,移到下一个li时,跳过if,重新获取target与id?? timer = null; //这样的话,返回什么呢?? // 因为active是全局变量???? },300); //300毫秒后执行,这样当鼠标从一级菜单转换到二级菜单时,中间划过其他li也不会触动其对应的二级菜单,因为有延迟 } 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') } }) });
函数的js代码:
/** * Created by sofiaZ on 17/7/27. */ function sameSign(a, b) { return(a ^ b) >=0; //a^b为a按位异或b,若结果为正(最高位为0),则a和b要么同正要么同负) } function vector(a,b){ return{ x: b.x- a.x, y: b.y- a.x } } 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 + elem.height() }; return isPointInTrangle(currMousePos, leftCorner, topLeft, bottomLeft)
不用这样,只要把边距去掉在 li 加点边缘就行 就解决了
因为你第32行是以主菜单(#test)绑定事件的 而主菜单有一个上边缘和一个下边缘 当你移到这个上边缘或者下边缘却没移到 li 元素上时 二级菜单sub显示了 但是二级菜单里面的元素却依然处于display:none状态
你可以将32行改为('#test li')绑定到 li元素上 同时修改55行为.on('mouseenter',function(e)就可以了
不过我也遇到过问题 就是没修改之前 我设置setTimeOut 能正常运行 但是我修改后 就失效了 不知道有没有人知道是什么原因
应该是 #sub的div样式中的padding的问题。
应该是id=sub的div吧,看看样式