Skip to content

菜单三角形方案

解决滑动需要设置延迟,来解决误滑其他菜单方案

菜单原理图片

js
const mouseLocs = []
let lastDelayLoc = {}

function menu() {
  // 获取菜单元素的位置和尺寸信息
  const offset = document.querySelector('.menu').getBoundingClientRect()

  // 定义右上角和右下角两个点的坐标
  const rightTop = {
    x: offset.right,
    y: offset.top
  }

  const rightBottom = {
    x: offset.right,
    y: offset.bottom
  }

  // 获取鼠标位置的前一个和当前的坐标
  const prevLoc = mouseLocs[0]
  const loc = mouseLocs.slice(-1)[0]

  // 检查鼠标是否在元素外部,或者当前位置与上一个延迟位置相同
  if (
    !isInsideElement(prevLoc, offset)
    || isSameLoc(loc, lastDelayLoc)
  )
    return 0 // 如果不满足条件,则不触发延迟,返回0

  // 计算当前位置到右上角和右下角的斜率
  const rightTopSlope = slope(loc, rightTop)
  const rightBottomSlope = slope(loc, rightBottom)

  // 计算前一个位置到右上角和右下角的斜率
  const prevRightTopSlope = slope(prevLoc, rightTop)
  const prevRightBottomSlope = slope(prevLoc, rightBottom)

  // 如果鼠标移动方向符合条件,则记录当前位置为延迟位置,并返回延迟时间150ms
  if (
    rightTopSlope < prevRightTopSlope
    && rightBottomSlope > prevRightBottomSlope
  ) {
    lastDelayLoc = loc
    return 150
  }

  return 0 // 如果不满足条件,则不触发延迟,返回0

  // 辅助函数:检查坐标是否在指定元素的范围内
  function isInsideElement(loc, offset) {
    return (
      loc.x >= offset.left
      && loc.x <= offset.right
      && loc.y >= offset.top
      && loc.y <= offset.bottom
    )
  }

  // 辅助函数:检查两个坐标是否相同
  function isSameLoc(loc1, loc2) {
    if (!loc2)
      return false

    return loc1.x === loc2.x && loc1.y === loc2.y
  }

  // 辅助函数:计算通过两个点的直线斜率
  function slope(a, b) {
    return (b.y - a.y) / (b.x - a.x)
  }
}
const mouseLocs = []
let lastDelayLoc = {}

function menu() {
  // 获取菜单元素的位置和尺寸信息
  const offset = document.querySelector('.menu').getBoundingClientRect()

  // 定义右上角和右下角两个点的坐标
  const rightTop = {
    x: offset.right,
    y: offset.top
  }

  const rightBottom = {
    x: offset.right,
    y: offset.bottom
  }

  // 获取鼠标位置的前一个和当前的坐标
  const prevLoc = mouseLocs[0]
  const loc = mouseLocs.slice(-1)[0]

  // 检查鼠标是否在元素外部,或者当前位置与上一个延迟位置相同
  if (
    !isInsideElement(prevLoc, offset)
    || isSameLoc(loc, lastDelayLoc)
  )
    return 0 // 如果不满足条件,则不触发延迟,返回0

  // 计算当前位置到右上角和右下角的斜率
  const rightTopSlope = slope(loc, rightTop)
  const rightBottomSlope = slope(loc, rightBottom)

  // 计算前一个位置到右上角和右下角的斜率
  const prevRightTopSlope = slope(prevLoc, rightTop)
  const prevRightBottomSlope = slope(prevLoc, rightBottom)

  // 如果鼠标移动方向符合条件,则记录当前位置为延迟位置,并返回延迟时间150ms
  if (
    rightTopSlope < prevRightTopSlope
    && rightBottomSlope > prevRightBottomSlope
  ) {
    lastDelayLoc = loc
    return 150
  }

  return 0 // 如果不满足条件,则不触发延迟,返回0

  // 辅助函数:检查坐标是否在指定元素的范围内
  function isInsideElement(loc, offset) {
    return (
      loc.x >= offset.left
      && loc.x <= offset.right
      && loc.y >= offset.top
      && loc.y <= offset.bottom
    )
  }

  // 辅助函数:检查两个坐标是否相同
  function isSameLoc(loc1, loc2) {
    if (!loc2)
      return false

    return loc1.x === loc2.x && loc1.y === loc2.y
  }

  // 辅助函数:计算通过两个点的直线斜率
  function slope(a, b) {
    return (b.y - a.y) / (b.x - a.x)
  }
}