先上效果图(gif自己录制的,有点难看抱歉,工具licecap)
实现思路
HTML结构
JS
li作为鼠标移入(mouseenter
)和鼠标移出(mouseleave
)的载体。
div作为动画执行的载体。
CSS
div采用absolute
定位,通过top、left改变它的位置。
由于div的top、left可能会超出li的大小,所以要设置li的overflow:hidden;
JS
1、采用JS操纵CSS3 transition动画
2、如何判断鼠标移入移除的方向
鼠标坐标的相关知识
MouseEvent对象
下面介绍几个MouseEvent
中坐标的相关知识:
(clientX,clientY):
以可视区域为参考系的坐标。
(pageX,pageY):
以整个页面(包括滚动条卷出的区域)为参考系的坐标。
(screenX,screenY):
以你的电脑屏幕为参考系的坐标。
获取某个元素内部的坐标
Box = element.getBoundingClientRect();
return {
x: e.clientX - elementBox.left,y: e.clientY - elementBox.top
};
}
计算元素左上角的坐标
获取元素的宽度和高度(不要认为是width和height 新手特别容易犯错)
简单的封装一下CSS3 transition动画
属性,这里可能多个,所以采用函数的方式(可选) callback: 回调函数(可选) */
function animation(options){
if(!options.obj) {
return false;
}
//设置默认持续时间
options.speed = options.speed || '.5s';
options.obj.style.transition = "all " + options.speed + " ease-in-out";
options.changeStyle.call(options.obj);
var flag = false;
options.obj.addEventListener('transitionend',function(){
//这里主要由于transitionend在每个<a href="https://www.jb51.cc/tag/shuxing/" target="_blank" class="keywords">属性</a>的动画执行完多会走一遍,所以我们要让它只执行一次。
if(!flag) {
options.callback && options.callback();
}
},false);
}
如何确定方向
这里要用到数学中的正切相关的概念,我自己画了一张图,不知道你们能不能看特明白:(奇丑。。。)
得到元素的运动方向
= 1) {
//上方
return 1;
}
else if(disY > 0 && Math.abs(disY / disX) >= 1) {
//下
return 2;
}
else if(disX < 0 && Math.abs(disY / disX) < 1) {
//左
return 3;
}
else {
//右
return 4;
}
}
启动事件的代码,有注释
效果)
_this.animationElement.style.transition = "";
//得到运动的方向,要确定动画载体的开始位置
switch(dir){
case 1:
_this.animationElement.style.top = "-100%";
_this.animationElement.style.left = "0";
break;
case 2:
_this.animationElement.style.top = "100%";
_this.animationElement.style.left = "0";
break;
case 3:
_this.animationElement.style.top = "0";
_this.animationElement.style.left = "-100%";
break;
case 4:
_this.animationElement.style.top = "0";
_this.animationElement.style.left = "100%";
break;
}
//异步执行
_this.timeId = setTimeout(function(){
animation({
obj: _this.animationElement,speed: _this.speed,changeStyle: function(){
this.style.top = "0";
this.style.left = "0";
}
});
},20);
},false);
_this.targetElement.addEventListener('mouseleave',function(e){
var left,top;
var point = {
x: e.pageX,y: e.pageY
}
clearTimeout(_this.timeId);
_this.animationElement.style.transition = "";
var dir = getDirection(_this.targetElement,point);
switch(dir) {
case 1:
top = '-100%';
left = '0';
break;
case 2:
top = '100%';
left = "0";
break;
case 3:
left = "-100%";
top = "0";
break;
case 4:
left = "100%";
top = "0";
break;
}
_this.timeId = setTimeout(function(){
animation({
obj: _this.animationElement,changeStyle: function(){
this.style.top = top;
this.style.left = left;
}
});
},false);
}