原生js判断鼠标移入方向,图片特效

  • 先来个最终效果
  • 需求,判断出鼠标从元素的哪个方向移入
  • 封装一下


搞vue搞uniapp搞得脑子都发木了,有些时候呢一些原生的,底层的东西都要忘脖子后去了,今天呢就来个原生js的小demo。

先来个最终效果

jQuery 怎么判断是鼠标触发的事件还是键盘触发的事件 js判断鼠标是否停止移动_js

需求,判断出鼠标从元素的哪个方向移入

在判断这个移入方向之前呢,我们要搞清楚一些事情,请看下图

jQuery 怎么判断是鼠标触发的事件还是键盘触发的事件 js判断鼠标是否停止移动_Math_02


我们在获取鼠标点击的位置,所在的位置时会有很多的值,offset,page, screen,client,我呢没有写全,但其实我们常用的主要有,page, offset, client,我的图片中没有画出client因为不是很好表现,总结说就是,page包含滚动条,但是client不包括。请看下图:

jQuery 怎么判断是鼠标触发的事件还是键盘触发的事件 js判断鼠标是否停止移动_js_03


小伙伴先不要纠结元素位置为什么是offsetLeft这个玩意还是要根据需求来的,不可能一个做法就万能了。 js里提供了一个根据坐标位置求角度的公式:

Math.atan2(y, x) * (180 / Math.PI)

ok我们可以知道鼠标移入的角度了,下面还是有一系列的问题,在看这张图:

jQuery 怎么判断是鼠标触发的事件还是键盘触发的事件 js判断鼠标是否停止移动_js_04


貌似我们找到了根据角度来判断移入方向的窍门,但是这里有两个问题:

  1. 是上面的公式算出来的结果是0到180度然后-180到0度。
    这么我们就要解决一下角度与方向的问题那么再来张图,
    来图之前呢先上一个式子

Math.atan2(y, x) * (180 / Math.PI) + 180

这样我们就可以得到0~360度的一个数值了,那么他们的方向大概是这样的

jQuery 怎么判断是鼠标触发的事件还是键盘触发的事件 js判断鼠标是否停止移动_js_05


好第一个问题就解决了,那么第二个问题是啥呢?

2. 以上说的都是元素是个正方形,那要是长方形呢?

jQuery 怎么判断是鼠标触发的事件还是键盘触发的事件 js判断鼠标是否停止移动_Math_06


那这个问题我们怎么解决呢?这个要从开始算坐标值时就入手

x = clientX - (offsetLeft + width/2) * (width > height ? height / width : 1)
y = clientY - (offsetTop + height/2) * (height > width ? width / height : 1)

也就是说在计算坐标值时把元素的宽高比考虑进去,这样就不怕当元素为长方形时判断出现错误了。

封装一下
// 获取滚动条滚动距离
function getScrollOffset() {
    if (typeof window.pageXOffset === 'number') {
        return {
            x: window.pageXOffset,
            y: window.pageYOffset
        }
    } else {
        return {
            x: document.documentElement.scrollLeft + document.body.scrollLeft,
            y: document.documentElement.scrollTop + document.body.scrollTop
        }
    }
}
function getDirection(wrapper, e, origin) {
    // 盒子位置
    var boxTop = wrapper.offsetTop;
    var boxLeft = wrapper.offsetLeft;
    // 元素尺寸
    var oHeight = origin.offsetHeight;
    var oWidth = origin.offsetWidth;
    // 滚动条位置
    var scrollTop = getScrollOffset().y;
    var scrollLeft = getScrollOffset().x;
    // 元素的位置
    var oTop = origin.offsetTop + boxTop;
    var oLeft = origin.offsetLeft + boxLeft;
    // 元素相对视口的位置
    var top = oTop - scrollTop;
    var left = oLeft - scrollLeft;
    // 鼠标进入元素是的位置
    var inX = e.clientX || (e.pageX - scrollLeft);
    var inY = e.clientY || (e.pageY - scrollTop);
    // 鼠标以元素为中心的坐标
    var x = (inX - (oWidth / 2 + left)) * (oWidth > oHeight ? oHeight / oWidth : 1);
    var y = (inY - (oHeight / 2 + top)) * (oHeight > oWidth ? oWidth / oHeight : 1);
    // 根据鼠标位置求出 角度
    var d = (Math.round((Math.atan2(y, x) * (180 / Math.PI) + 180) / 90) + 3) % 4;
    var dirArr = ['top', 'right', 'bottom', 'left'];
    return dirArr[d]
}

最后那个算法我也忘了是在哪看的了,好像是某个前辈告诉我的。

动画函数的封装下次再说喽,闪人。