网络编程 
首页 > 网络编程 > 浏览文章

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

(编辑:jimmy 日期: 2024/11/16 浏览:3 次 )

这是一个js实现京东无延迟菜单效果,感觉很好,分享给大家...

先来理清思路:

1.开发基本的菜单结构    

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

3.假如延迟解决移动问题,切换子菜单时候,用setTimeout设置延迟

debounce去抖技,在事件被频繁触发是,只执行一次处理

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

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

运用到向量

二位向量叉乘公式

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

最终效果:鼠标自然的移动和点击到子菜单

切换时无延迟

下面开始代码:

开发基本的菜单结构

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

解决第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)
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:ES6中箭头函数的定义与调用方式详解
下一篇:javascript实现延时显示提示框效果
微软与英特尔等合作伙伴联合定义“AI PC”:键盘需配有Copilot物理按键
几个月来,英特尔、微软、AMD和其它厂商都在共同推动“AI PC”的想法,朝着更多的AI功能迈进。在近日,英特尔在台北举行的开发者活动中,也宣布了关于AI PC加速计划、新的PC开发者计划和独立硬件供应商计划。
在此次发布会上,英特尔还发布了全新的全新的酷睿Ultra Meteor Lake NUC开发套件,以及联合微软等合作伙伴联合定义“AI PC”的定义标准。
友情链接:杰晶网络 DDR爱好者之家 南强小屋 黑松山资源网 白云城资源网 网站地图 SiteMap