穿墙效果附加注释,附加鼠标进入方向算法

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
* {
margin: 0;
padding: 0;
list-style: none;
}
ul {
overflow: hidden;
width: 630px;
margin: 100px auto;
}
ul li {
float: left;
position: relative;
width: 200px;
height: 200px;
background: #ccc;
margin: 5px;
overflow: hidden;
}
ul li span {
position: absolute;
width: 100%;
height: 100%;
background: rgba(255, 0, 0, 0.3);
left: -200px;
top: 0;
}
</style>
<script>
function getStyle(obj, sName) {
// 获取元素对象的css属性值兼容ie和其他浏览器
return (obj.currentStyle || getComputedStyle(obj, false))[sName];
}
function move(obj, json, options) {
// obj 为元素对象、json为设定最后结果对象、options为设置对象
// 给options设定默认值
options = options || {};
// 设定持续时间
options.duration = options.duration || 700;
// 设定运动方式
options.easing = options.easing || ‘ease-out‘;
// 定义空对象
var start = {};
// 定义差值对象
var dis = {};
// 遍历设定设定最后结果对象
for (var name in json) {
// 将设定最后结果对象中的属性值与初始值取差值
start[name] = parseFloat(getStyle(obj, name) );
dis[name] = json[name] - start[name];
}
// 下方每30毫秒执行一次运动,这里获取运动总次数
var count = Math.floor(options.duration / 30);
// 设定运动初始次数
var n = 0;
// 清空间歇调用,如果以前定义过则清除动画次数
clearInterval(obj.timer);
// 用obj.timer来代替动画次数
obj.timer = setInterval(function() {
n++;
for (var name in json) {
switch (options.easing) {
case ‘linear‘:
var cur = start[name] + dis[name] * n / count;
break;
case ‘ease-in‘:
var a = n / count;
var cur = start[name] + dis[name] * Math.pow(a, 3);
break;
// 次数默认使用ease-out
case ‘ease-out‘:
var a = 1 - n / count;
// cur为每次运动后的元素的落脚位置
var cur = start[name] + dis[name] * (1 - Math.pow(a, 3));
break;
}
if (name == ‘opacity‘) {
obj.style.opacity = cur;
obj.style.filter = ‘alpha(opacity:‘ + cur * 100 + ‘)‘;
} else {
obj.style[name] = cur + ‘px‘;
}
}
// 如果运动完成,则清除运动(obj.timer)
if (n == count) {
// 清除动画次数
clearInterval(obj.timer);
// 回调函数
options.complete && options.complete();
}
}, 30);
}
function a2d(n) {
// n 为弧度 ;弧度转化为角度
return n * 180 / Math.PI;
}
function hoverDir(ev, obj) {
// 领边长度
var a = ev.clientX - obj.offsetLeft - obj.offsetWidth / 2;
// 对边长度
var b = obj.offsetTop + obj.offsetHeight / 2 - ev.clientY;
// 通过角度来获得鼠标进入的方向;0为左侧、 1为下 、2为右、 3为上
// Math.atan2(b, a)为获取弧度公式
// a2d(n)为获取角度公式
return Math.round((a2d(Math.atan2(b, a)) + 180) / 90) % 4;
}
function through(obj) {
var oS = obj.children[0]; //这个是li里面的span
// 鼠标进入的时候
obj.onmouseenter = function(ev) {
// 如果不知道ev是啥 就打印出来看看
console.log(ev)
// 兼容ie浏览器
var oEvent = ev || event;
// obj为li,将oEvent和 li 作为参数,dir为返回值代表着鼠标的进入方向
var dir = hoverDir(oEvent, obj);
switch (dir) {
case 0:
//左,oS为li中的 span
oS.style.left = ‘-200px‘;
oS.style.top = 0;
break;
case 1:
//下
oS.style.left = 0;
oS.style.top = ‘200px‘;
break;
case 2:
//右
oS.style.left = ‘200px‘;
oS.style.top = 0;
break;
case 3:
//上
oS.style.left = 0;
oS.style.top = ‘-200px‘;
break;
}
//oS是li里面的span,设置运动
// move(obj, json, options) obj = oS 、 json = { left: 0, top: 0 }、options取默认值,并且没有回调函数
move(oS, { left: 0, top: 0 });
};
// 鼠标离开时
obj.onmouseleave = function(ev) {
var oEvent = ev || event;
var dir = hoverDir(oEvent, obj);
switch (dir) {
case 0:
// move(obj, json, options) obj = oS 、 json = { left: -200, top: 0 }、options取默认值,并且没有回调函数
move(oS, { left: -200, top: 0 });
break;
case 1:
move(oS, { left: 0, top: 200 });
break;
case 2:
move(oS, { left: 200, top: 0 });
break;
case 3:
move(oS, { left: 0, top: -200 });
break;
}
};
}
window.onload = function() {
var aLi = document.getElementsByTagName(‘li‘);
for (var i = 0; i < aLi.length; i++) {
through(aLi[i]);
}
};
</script>
</head>
<body>
<ul>
<li><span></span></li>
<li><span></span></li>
<li><span></span></li>
<li><span></span></li>
<li><span></span></li>
<li><span></span></li>
</ul>
</body>
</html>
原文:https://www.cnblogs.com/hss-blog/p/9040431.html