美文网首页
菜单栏的切换

菜单栏的切换

作者: 晴天小码农 | 来源:发表于2017-11-30 11:24 被阅读0次

    HTML 代码 CSS 省略了。

            <ul>
                <li data-id="a">
                    <span>家用电器</span>
                </li>
                <li data-id="b">
                    <span>家用电器</span>
                </li>
                <li data-id="c">
                    <span>家用电器</span>
                </li>
                
            </ul>
    
            <div id='sub' class="none">
                <div id='a' class="sub_content ">
                    <dl>
                        <dt>
                            <a href="">tv <i>&gt;</i></a>
                        </dt>
                        <dd>
                            <a href="">sdkjfhasdkjfhaskj</a>
                            <a href="">sdkjfhasdkjfhaskj</a>
                            <a href="">sdkjfhasdkjfhaskj</a>
                            <a href="">sdkjfhasdkjfhaskj</a>
                        </dd>
                    </dl>
                </div>
                <div id='b' class="sub_content ">
                    <dl>
                        <dt>
                            <a href="">tv <i>&gt;</i></a>
                        </dt>
                        <dd>
                            <a href="">sAAAAAAAAAAAAkjfhaskj</a>
                            <a href="">sdkjfhasdkjfhaskj</a>
                            <a href="">sdkjfhasdkjfhaskj</a>
                            <a href="">sdkjfhasdkjfhaskj</a>
                        </dd>
                    </dl>
                </div>
                <div id='c' class="sub_content">
                    <dl>
                        <dt>
                            <a href="">tv <i>&gt;</i></a>
                        </dt>
                        <dd>
                            <a href="">sdkBBBBBBBBBBBBBBaskj</a>
                            <a href="">sdkjfhasdkjfhaskj</a>
                            <a href="">sdkjfhasdkjfhaskj</a>
                            <a href="">sdkjfhasdkjfhaskj</a>
                        </dd>
                    </dl>
                </div>
            </div>
        </div>
    

    JS 代码 使用Jquery 利用mousetern mouseout时间 事件委托

    $( () => {
    $(() => {
        // 子菜单
        let sub = $('#sub');
        // 主菜单选中
        let activeRow;
        // 子菜单选中
        let activeMenu;
        // 保存定时器
        let timer;
    
        // 预测用户是不是想移入二级菜单  li标签到菜单的上边缘 和 下边缘组成一个三角形,利用向量判断是不是绘制了一个三角形
    
        // 追踪鼠标的 位置 只需要三个值
    
        let mouseTrack = []
    
        // 把鼠标绑定的事件绑定在document上
    
        mouseHandler = (e) => {
    
            mouseTrack.push({
    
                x: e.pageX,
                y: e.pageY
            })
    
            // 只保存三个值 大于三个值 去掉第一个值
            if (mouseTrack.length > 3) {
    
                mouseTrack.shift();
            }
    
        }
    
    
        $('#test')
            .on("mouseenter", () => {
    
                sub.removeClass('none');
    
                $(document).bind("mousemove", mouseHandler)
            })
            .on("mouseleave", () => {
    
                sub.addClass('none');
    
                // 鼠标移动事件的解绑
    
                $(document).unbind("mousemove", mouseHandler);
            })
            // 事件委托
            .on('mouseenter', 'li', (e) => {
    
                // 当鼠标从一个li到另一个li menu会马上跟着变化 用户就无法点击 利用定时器
    
                if (timer) {
    
                    clearTimeout(timer);
                }
    
                // 第一次鼠标移入
                if (!activeRow) {
    
                    activeRow = $(e.target).addClass('active');
    
                    activeMenu = $("#" + activeRow.data("id"));
    
                    activeMenu.removeClass("none");
                }
    
                let currenMouse = mouseTrack[2];
                // 上一次的鼠标位置
                let leftCorner = mouseTrack[1];
    
                let delay = needDealy(sub,leftCorner,currenMouse) ;
                // 如果用户准备移入对应的子菜单
                if(delay) {
    
                    timer = setTimeout(() => {
        
                        // 鼠标移入另外一个li
                        activeRow.removeClass('active');
        
                        activeMenu.addClass('none');
        
                        //  重新指向选中的li
        
                        activeRow = $(e.target);
        
                        activeMenu = $("#" + activeRow.data("id"));
        
                        activeRow.addClass("active");
        
                        activeMenu.removeClass("none");
        
                        timer = null;
                    }, 300);
                }else{
    
                    var perActiveRow = activeRow;
    
                    var perActiveMenu = activeMenu;
    
                    activeRow = $(e.target);
    
                    activeMenu = $('#' + activeRow.data('id'));
    
                    perActiveRow.removeClass('active');
    
                    perActiveMenu.addClass('none');
    
                    activeRow.addClass('active');
    
                    activeMenu.removeClass('none')
                }
    
    
    
            });
    
        // 判断用户鼠标是否准备移入当前选中的li对应的menu 判断当前鼠标位置是否在 与当面位置上一次的位置 与菜单的左上角和左下角组成的三角形中 利用三个向量乘积是否大于0
    
        // 向量计算的工具函数
        // 计算2个坐标点的构成向量
        function vector(a, b) {
    
            return {
                x: a.x - b.x,
                y: a.y - b.y
            }
        }
        // 向量乘积
        function vectorProduct(a, b) {
    
            return a.x * b.y - a.y * b.x;
        }
    
        // 判断是否在三角形内
    
        function isPositionInAngle(p, a, b, c) {
    
            let pa = vector(p, a);
            let pb = vector(p, b);
            let pc = vector(p, c);
    
            let t1 = vectorProduct(pa, pb);
            let t2 = vectorProduct(pa, pc);
            let t3 = vectorProduct(pb, pc);
    
            return t1 * t2 * t3 > 0;
            // 如果大于0 表示在三角形内
        }
    
        // 判断用户是否会移入当选选中li 对应的子菜单
    
        // ele 菜单 leftCorner 鼠标上一次的位置 currenMouse鼠标当前位置
        function needDealy(ele, leftCorner, currenMouse) {
    
            // 菜单的位置
            let offset = ele.offset();
            // 菜单左上角的位置
            let topLeft = {
    
                x: offset.left,
                y: offset.top
            }
            // 菜单左下角那个点的位置
            let bottomLeft = {
    
                x: offset.left,
                y: offset.top + ele.height
            }
    
    
            return isPositionInAngle(currenMouse,leftCorner,topLeft,bottomLeft) ;
        }
    
    })
    

    这样子就可以做出完美的菜单栏无延迟的切换了.
    知识点 事件委托 提前判断用户行为

    相关文章

      网友评论

          本文标题:菜单栏的切换

          本文链接:https://www.haomeiwen.com/subject/gxambxtx.html