Js实现京东无延迟菜单效果(demo)

先来理清思路

1.开发基本的菜单结构
2.开发普通的二级菜单效果
3.假如延迟解决移动问题 切换子菜单时候,用setTimeout设置延迟 debounce去抖技 在事件被频繁触发是,只执行一次处理
4.解决延迟引入的新问题 跟踪鼠标的移动 用鼠标当前位置,和鼠标上一次位置与子菜单上下边缘的三角形区域进行比较 运用到向量 二位向量叉乘公式 用叉乘法判断点在三角形内
最终效果:鼠标自然的移动和点击到子菜单 切换时无延迟

html代码 1.开发基本的菜单结构




    
    京东菜单无刷新
    
    
    

    


2.完成开发普通的二级菜单效果

3.用setTimeout设置延迟 debounce去抖技 在事件被频繁触发时,只执行一次处理

$(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')
            }
        })
})

4. 解决延迟引入的新问题

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)
}
Js实现京东无延迟菜单效果(demo)_第1张图片
1105168-20170602184106164-70570130.gif

原博地址http://www.cnblogs.com/6kou/p/jd.html

你可能感兴趣的:(Js实现京东无延迟菜单效果(demo))