【前-demo】慕课网—无延迟二级菜单加载及demo

前记

演示效果

【前-demo】慕课网—无延迟二级菜单加载及demo_第1张图片

重点

1、页面布局及CSS知识

2、如何实现无延迟加载

所需框架

Jquery

实现笔记

html

左半边的一级菜单,布局使用ul和li标签,代码片段:

  
  • 家用电器
  • …………
  • 手机 / 运用商 / 数码

说明:
(1)ul是无序列表,li标签定义列表的内容,自带·的样式,它们都是块级元素

(2)data-*是自定义数据,用于存储页面或应用程序的私有自定义数据,赋予我们在所有 HTML 元素上嵌入自定义 data 属性的能力

右边二级菜单的html结构

首先使用div作为父级容器,然后在用若干个div表示每一个一级菜单所对应的二级菜单。

在每一个二级菜单div中,使用了dl、dt、dd元素作为布局的标签,实例代码部分如下:

 

说明:
(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)三角形的图如下所示:


【前-demo】慕课网—无延迟二级菜单加载及demo_第2张图片
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实现京东无延迟菜单效果

结束:附上源码 码云:JS实现京东无延迟菜单效果

微信公众号

若有疑问可以QQ联系笔者,虽然不一定100%解决你的问题,但是可以交流探讨一波:2276604211

顺便打个内推广告:如果有想入职中国银联上海技术开发的童鞋,也可以加上面的QQ资讯,笔者可以帮你回答一些相关问题~~

你可能感兴趣的:(【前-demo】慕课网—无延迟二级菜单加载及demo)