原生js判断鼠标移入方向,图片特效
搞vue搞uniapp搞得脑子都发木了,有些时候呢一些原生的,底层的东西都要忘脖子后去了,今天呢就来个原生js的小demo。
先来个最终效果
需求,判断出鼠标从元素的哪个方向移入
在判断这个移入方向之前呢,我们要搞清楚一些事情,请看下图
我们在获取鼠标点击的位置,所在的位置时会有很多的值,offset,page, screen,client,我呢没有写全,但其实我们常用的主要有,page, offset, client,我的图片中没有画出client因为不是很好表现,总结说就是,page包含滚动条,但是client不包括。请看下图:
小伙伴先不要纠结元素位置为什么是offsetLeft这个玩意还是要根据需求来的,不可能一个做法就万能了。 js里提供了一个根据坐标位置求角度的公式:
Math.atan2(y, x) * (180 / Math.PI)
ok我们可以知道鼠标移入的角度了,下面还是有一系列的问题,在看这张图:
貌似我们找到了根据角度来判断移入方向的窍门,但是这里有两个问题:
- 是上面的公式算出来的结果是0到180度然后-180到0度。
这么我们就要解决一下角度与方向的问题那么再来张图,
来图之前呢先上一个式子
Math.atan2(y, x) * (180 / Math.PI) + 180
这样我们就可以得到0~360度的一个数值了,那么他们的方向大概是这样的
好第一个问题就解决了,那么第二个问题是啥呢?
2. 以上说的都是元素是个正方形,那要是长方形呢?
那这个问题我们怎么解决呢?这个要从开始算坐标值时就入手
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]
}
最后那个算法我也忘了是在哪看的了,好像是某个前辈告诉我的。
动画函数的封装下次再说喽,闪人。