求问:我这个下移正常,上移延迟

来源:1-1 课程介绍

qq_老老实人_0

2018-05-29 15:53

$(document).ready(function () {
    var sub = $('#sub');
    var row;   //每个<li>
    var menu;  //二级菜单
    var timer;
    var mouseInsub = false;  //鼠标是否进入到二级菜单的一个flag
    var mouseTrack = [];
    var moveHandler = function (e) {
      mouseTrack.push({     //插入鼠于当前页面的坐标
          x: e.pageX,
          y: e.pageY
      });
      if(mouseTrack.length > 3){     //数组中只需要保存当前位置和上一次的位置
          mouseTrack.shift();
      }
    };
    //检查鼠标是否移入到二级菜单,如果移到了二级菜单,则下面定时器直接返回
    sub.on("mouseenter",function () {
        mouseInsub = true;
    }).on("mouseleave",function () {
        mouseInsub = false;
    });
    $("#test")
        .on("mouseenter",function (e) {  //mouseover移入子元素会触发mouseout,这个不会
            sub.removeClass("none");
            //常识,mousemove绑定在document上,鼠标在div上移动触发该事件,移出时记得清除
            $(document).bind("mousemove",moveHandler);
        })
        .on("mouseleave",function (e) {
            sub.addClass("none");
            if(row){
                row.removeClass("active");
                row = null;
            }
            if(menu){
                menu.addClass("none");
                menu = null;
            }
            $(document).unbind("mousemove",moveHandler);
        })
        .on("mouseenter","li",function (e) {    //只在$("#test")下的“li”才触发
            if(!row){
                row = $(e.target).addClass("active"); //e.target当前指向的真正元素
                menu = $("#" + row.data("id"));
                menu.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);
            console.log(currMousePos, leftCorner,delay);
            if(delay){  //如果在三角形内,这需要延迟
                timer = setTimeout(function () { //防止鼠标打斜进入二级菜单
                        if(mouseInsub){ //鼠标在二级菜单里的话
                            return;
                        }
                        row.removeClass("active"); //得写在下面,写在上面row未定义报错
                        menu.addClass("none");
                        row = $(e.target).addClass("active");
                        menu = $("#" + row.data("id")); //data-xx属性都可以这样,如data-id
                        menu.removeClass("none");
                    }
                    ,300);
            }else{
                row.removeClass("active"); //移除上一任样式
                menu.addClass("none");
                row = $(e.target).addClass("active"); //给当前所指li添加样式
                menu = $("#" + row.data("id"));
                menu.removeClass("none");
            }
       })
});
function isSameSign(a,b) {
    return (a ^ b) >= 0;
    //a异或b大于等于则认为符合相同
    //最高位的异或运算,不相同返回1
}
function vector(a,b) {  //向量
    var a = a || {};
    var b = b || {};
    return{     //终点坐标 - 起点坐标
        x: b.x - a.x,
        y: b.y - a.y
    };
}
function vectorProduct(v1,v2) {  //向量X乘公式
    return v1.x * v2.y - v1.y * v2.x;
    //向量1的x坐标 * 向量2的y坐标  -  向量1的y坐标 * 向量2的x坐标
}
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);  //返回向量X乘结果
    var t2 = vectorProduct(pb, pc);
    var t3 = vectorProduct(pc, pa);
   
    return isSameSign(t1,t2) && isSameSign(t2,t3);
    
}
function needDelay(elem,leftCorner,currMousePos) {
    if (!currMousePos || !leftCorner) {  
        return;
    }
    var offset = elem.offset(); //jquery的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);
}


写回答 关注

1回答

  • 业余奶茶品鉴师
    2018-08-16 11:14:06

    跟老师的代码一样的吧

JS实现京东无延迟菜单效果

JS模拟京东商城无延迟菜单效果,学习菜单结构和样式处理

57661 学习 · 138 问题

查看课程

相似问题