广告位招租虚拟主机

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

2017-06-05  来源:cnblogs.com  我有话说  收藏本文

这是一个js实现京东无延迟菜单效果,感觉很好,分享给大家。先来看实例展示:

70570130.gif

(点击放大)

先来理清思路:

1.开发基本的菜单结构;

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

3.假如延迟解决移动问题 

切换子菜单时候,用setTimeout设置延迟

debounce去抖技

在事件被频繁触发时,只执行一次处理

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

跟踪鼠标的移动

用鼠标当前位置,和鼠标上一次位置与子菜单上下边缘的三角形区域进行比较

运用到向量

二位向量叉乘公式

用叉乘法判断点在三角形内

最终效果:鼠标自然的移动和点击到子菜单,切换时无延迟。

代码如下:

开发基本的菜单结构

<!doctype html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>京东菜单无刷新</title>
    <script src="js/jquery-1.7.2.min.js"></script>
    <script src="js/mche.js"></script>
    <script src="js/function.js"></script>

    <style>
        .wrap{
            position:relative;
            width:200px;
            left:50px;
            top:50px;
        }

        ul{
            padding:15px;
            margin:9;
            list-style:none;
            background:#6c6669;
            color:#ffffff;
            border-right-width:0;
        }

        /*水平居中*/
        li{
            display:block;
            height:30px;
            line-height: 30px;
            padding-left:12px;
            cursor:pointer;
            font-size: 14px;
            position:relative;
        }

        /*鼠标移动上去的背景色*/
        li.active{
            background:#999395;
        }
    
        /*js可以很好地调用类,一般效果css实现就好*/
        li span:hover{
            color:#c81623;
        }

        /*隐藏的类*/
        .none{
            display: none;
        }

        /*二级菜单*/
        #sub{
            width:600px;
            position: absolute;
            border:1px solid #f7f7f7;
            background:#f7f7f7;
            box-shadow:2px 0 rgba(0,0,0,.3);
            left: 200px;
            top:0;
            box-sizing:border-box;
            margin: 0px;
            padding:10px;
        }

        .sub-content a{
            font-style:12px;
            color:#666;
            text-decoration:none;
        }

        .sub-content dd a{
            border-left:1px solid #e0e0e0;
            padding:0 1px;
            margin:4px 0;
        }

        .sub-content dl {
            overflow:hidden;
        }

        .sub-content dt{
            float: left;
            width:70px;
            font-weight: bold;
            clear:left;
            position:relative;
        }

        .sub-content dd {
            float: left;
            margin-left: 5px;
            border-top:1px solid #eee;
            margin-bottom: 5px;
        }

        .sub-content dt i{
            width:4px;
            height: 14px;
            font:400 9px/14px consolas;
            position: absolute;
            right:5px;
            top:5px;
        }
    </style></head><body><div class="wrap" id="test"><ul>
    <li data-id="a">
    <span>家用电器</span>    
    </li>
    <li data-id="b">
    <span>手机 / 运营商 / 数码</span>    
    </li>
    <li data-id="c">
    <span>电脑办公 / 办公</span>    
    </li>
    <li data-id="d">
    <span>家居 / 家具 / 家装 / 厨具</span>    
    </li>
    <li data-id="e">
    <span>男装 / 女装 / 童装 / 内衣 </span>    
    </li>
    <li data-id="f">
    <span>美妆个护 / 宠物 </span>    
    </li>
    <li data-id="g">
    <span>女鞋 / 箱包 / 钟表 / 珠宝 </span>    
    </li>
    <li data-id="h">
    <span>男鞋 / 运动 / 户外</span>    
    </li>
    <li data-id="i">
    <span>汽车 / 汽车用品  </span>    
    </li></ul>
    <div id="sub" class="none">
        <div id="a" class="sub-content none">
            <dl>
                <dt>
                    <a href="#">电视<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">曲面电视</a>
                    <a href="#">超薄电视</a>
                    <a href="#">HDR电视</a>
                    <a href="#">DLED电视</a>
                </dd>
                <dt>
                    <a href="#">空调<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">挂壁式空调</a>
                    <a href="#">柜式空调</a>
                    <a href="#">中央空调</a>
                    <a href="#">以旧换新</a>
                </dd>
                <dt>
                    <a href="#">洗衣机<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">滚筒式洗衣机</a>
                    <a href="#">洗烘一体机</a>
                    <a href="#">波轮洗衣机</a>
                    <a href="#">迷你洗衣机</a>
                </dd>
            </dl>
        </div>
        <div id="b" class="sub-content none">

            <dl>
                <dt>
                    <a href="#">手机通讯<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">手机</a>
                    <a href="#">对讲机</a>
                    <a href="#">以旧换新</a>
                    <a href="#">手机维修</a>
                </dd>
                <dt>
                    <a href="#">运营商<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">合约机</a>
                    <a href="#">选号机</a>
                    <a href="#">固定电话</a>
                    <a href="#">办宽带</a>
                </dd>
                <dt>
                    <a href="#">手机配件<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">手机壳</a>
                    <a href="#">贴膜</a>
                    <a href="#">手机存储卡</a>
                    <a href="#">数据线</a>
                </dd>
            </dl>
        </div>
        <div id="c" class="sub-content none">
            <dl>
                <dt>
                    <a href="#">电脑整机<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">笔记本</a>
                    <a href="#">游戏本</a>
                    <a href="#">平板电脑</a>
                </dd>
                <dt>
                    <a href="#">电脑配件<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">显示器</a>
                    <a href="#">CPU</a>
                    <a href="#">主板</a>
                </dd>
                <dt>
                    <a href="#">外设产品<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">鼠标</a>
                    <a href="#">键盘</a>
                    <a href="#">键盘套餐</a>
                </dd>
            </dl>
        </div>
        <div id="d" class="sub-content none">
            <dl>
                <dt>
                    <a href="#">厨具<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">烹饪锅具</a>
                    <a href="#">刀剪配件</a>
                    <a href="#">厨房配件</a>
                    <a href="#">水具酒具</a>
                </dd>
                <dt>
                    <a href="#">家纺<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">床品套件</a>
                    <a href="#">被子</a>
                    <a href="#">枕芯</a>
                    <a href="#">蚊帐</a>
                </dd>
                <dt>
                    <a href="#">生活日用<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">收纳用品</a>
                    <a href="#">雨伞雨具</a>
                    <a href="#">净化除味</a>
                    <a href="#">浴室用品</a>
                </dd>
            </dl>
        </div>
        <div id="e" class="sub-content none">
            <dl>
                <dt>
                    <a href="#">女装<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">商城同款</a>
                    <a href="#">当季热卖</a>
                    <a href="#">2017新品</a>
                    <a href="#">连衣裙</a>
                </dd>
                <dt>
                    <a href="#">男装<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">商城同款</a>
                    <a href="#">当季热卖</a>
                    <a href="#">2017新品</a>
                    <a href="#">牛仔裤</a>
                </dd>
            </dl>
        </div>
        <div id="f" class="sub-content none">
            <dl>
                <dt>
                    <a href="#">面部护肤<i>&gt</i></a>
                </dt>
                <dd>
                    <a href="#">补水保湿</a>
                    <a href="#">卸妆</a>
                    <a href="#">洁面</a>
                </dd>
            </dl>
        </div>
    </div></ul></body></html>

解决第2、3个问题

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

解决延迟引入的新问题

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)
}


当你看到这,也就实现了京东的无延迟菜单效果,同时也为你点赞,能看到这儿。

(责编:边缘)
阅读  次  |  打印  |  关闭
匿名评论

用微信扫一扫

新网巢