鼠标进入盒子方向判断

388 阅读2分钟

我们在网页上经常看到这种效果,就是鼠标从方块的四个不同方向移入方块时会展示不同的效果,实现这种效果首要的就是判断鼠标移入的方向,判断方向的方法有很多,今天我们就说其中的一种实现方法。

先看一个示意图

示意图

通过示意图我们很容易求出角α的弧度为:α = arctan(m/n),这里使用的是反三角函数中的反正切。同样的方法也可以得出β角的大小。 当β > α时,我们就可以确定a点在矩形的上方进入,反之就是在右方进入。四个方向都可以这样判断。由此,问题就简单了,我们需要求的就是这个角度,而求角度要知道的只是其对边和斜边,而根据点的位置,这两边非常容易得出。

判断方向的方法我封装成jquery插件。

// 传入参数必须是一个、四个或八个,传入的参数必须是回调函数,回调函数第一个参数代表当前对象
(function ($) {
  $.fn.extend({
    intoDir () {
      var arg = arguments
      return this.each(function (i, s) {
        // 监听mouseover事件
        $(s).mouseover(function (e) {
           // 获取进入点在块中的位置
          var x = e.offsetX, y = e.offsetY
          var sw = $(this).outerWidth(), sh = $(this).outerHeight()
          var dir = dirGet(x, y, sw, sh)
          // 根据方向依次运行需采取的动作
          var len = arg.length
          if (len == 1) {
            arg[0](this)
          } else if (len == 4) {
            if (dir == 'topleft' || dir == 'topright') {
              arg[0](this)
            }
            if (dir == 'righttop' || dir == 'rightbottom') {
              arg[1](this)
            }
            if (dir == 'bottomright' || dir == 'bottomleft') {
              arg[2](this)
            }
            if (dir == 'leftbottom' || dir == 'lefttop') {
              arg[3](this)
            }
          } else if (len == 8) {
            switch (dir) {
              case 'topleft':
                arg[0](this)
                break
              case 'topright':
                arg[1](this)
                break
              case 'righttop':
                arg[2](this)
                break
              case 'rightbottom':
                arg[3](this)
                break
              case 'bottomright':
                arg[4](this)
                break
              case 'bottomleft':
                arg[5](this)
                break
              case 'leftbottom':
                arg[6](this)
                break
              case 'lefttop':
                arg[7](this)
                break
              default: 
                throw new Error('错误的方向')
            }
          } else {
            throw new Error('传入参数数量错误')
          }
        })
        // 方向判断
        // x 点的left, y点的top, W块的宽度,H块的高度
        var dirGet = function (x, y, W, H) {
          var halfW = W / 2, halfH = H / 2
          var limit = Math.atan(halfH / halfW)
          var dirX = '', dirY = ''
          // 先判断点距离那条边较近,做一个粗略的位置判定
          if (x < halfW) {
            dirX = 'left'
          } else {
            dirX = 'right'
          }
          if (y < halfH) {
            dirY = 'top'
          } else {
            dirY = 'bottom'
          }
          // 依次求反正切值,判断具体方向
          switch (dirX + dirY) {
            case 'lefttop':
              if (Math.atan((halfH -y) / (halfW - x)) > limit) {
                return 'topleft'
              } else {
                return 'lefttop'
              }
            case 'leftbottom':
              if (Math.atan((y - halfH) / (halfW - x)) > limit) {
                return 'bottomleft'
              } else {
                return 'leftbottom'
              }
            case 'righttop':
              if (Math.atan((halfH - y) / (x - halfW)) > limit) {
                return 'topright'
              } else {
                return 'righttop'
              }
            case 'rightbottom':
              if (Math.atan((y - halfH) / (x - halfW)) > limit) {
                return 'bottomright'
              } else {
                return 'rightbottom'
              }
            default:
              throw new Error('未知的方向')
          }
        }
      })
    }
  })
})(jQuery)

jquery插件可直接使用,只需选择一个块元素即可。