JavaScript實(shí)現(xiàn)類似拉勾網(wǎng)的鼠標(biāo)移入移出效果
先上效果圖(gif自己錄制的,有點(diǎn)難看抱歉,工具licecap)
實(shí)現(xiàn)思路
HTML結(jié)構(gòu)
<ul>
<li>
<div class="bg">
<p>JS</p>
</div>
</li>
.....
</ul>
li作為鼠標(biāo)移入(mouseenter)和鼠標(biāo)移出(mouseleave)的載體。
div作為動(dòng)畫(huà)執(zhí)行的載體。
CSS
div采用absolute定位,通過(guò)top、left改變它的位置。
由于div的top、left可能會(huì)超出li的大小,所以要設(shè)置li的overflow:hidden;
JS
1、采用JS操縱CSS3 transition動(dòng)畫(huà)
2、如何判斷鼠標(biāo)移入移除的方向
鼠標(biāo)坐標(biāo)的相關(guān)知識(shí)
MouseEvent對(duì)象
下面介紹幾個(gè)MouseEvent中坐標(biāo)的相關(guān)知識(shí):
(clientX, clientY): 以可視區(qū)域?yàn)閰⒖枷档淖鴺?biāo)。
(pageX, pageY): 以整個(gè)頁(yè)面(包括滾動(dòng)條卷出的區(qū)域)為參考系的坐標(biāo)。
(screenX, screenY): 以你的電腦屏幕為參考系的坐標(biāo)。
獲取某個(gè)元素內(nèi)部的坐標(biāo)
function pointTo(element, e) {
var elementBox = element.getBoundingClientRect();
return {
x: e.clientX - elementBox.left,
y: e.clientY - elementBox.top
};
}
計(jì)算元素左上角的坐標(biāo)
function startPoint(element){
var x = 0,y = 0;
while(element != null) {
x += element.offsetLeft;
y += element.offsetTop;
element = element.offsetParent;
}
return {
x: x,
y: y
}
}
獲取元素的寬度和高度(不要認(rèn)為是width和height 新手特別容易犯錯(cuò))
offsetHeight與offsetWidth
簡(jiǎn)單的封裝一下CSS3 transition動(dòng)畫(huà)
/* options參數(shù): obj: 運(yùn)動(dòng)的對(duì)象 speed: 運(yùn)動(dòng)的持續(xù)時(shí)間(可選) changeStyle: 改變的屬性,這里可能多個(gè),所以采用函數(shù)的方式(可選) callback: 回調(diào)函數(shù)(可選) */
function animation(options){
if(!options.obj) {
return false;
}
//設(shè)置默認(rèn)持續(xù)時(shí)間
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在每個(gè)屬性的動(dòng)畫(huà)執(zhí)行完多會(huì)走一遍,所以我們要讓它只執(zhí)行一次。
if(!flag) {
options.callback && options.callback();
}
},false);
}
如何確定方向
這里要用到數(shù)學(xué)中的正切相關(guān)的概念,我自己畫(huà)了一張圖,不知道你們能不能看特明白:(奇丑。。。)
得到元素的運(yùn)動(dòng)方向
function getDirection(element,startPoint,pagePoint){
var halfWidth = element.offsetWidth / 2,halfHeight = element.offsetHeight / 2;
//得到中心點(diǎn)
var center = {
x: startPoint.x + halfWidth,
y: startPoint.y + halfHeight
}
//得到鼠標(biāo)偏離中心點(diǎn)的距離
var disX = pagePoint.x - center.x;
var disY = pagePoint.y - center.y;
if(disY < 0 && Math.abs(disY / disX) >= 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;
}
}
啟動(dòng)事件的代碼,有注釋
/* options中的參數(shù): 觸發(fā)事件的載體: targetElement 執(zhí)行動(dòng)畫(huà)的載體: animationElement */
function HoverAction(options) {
if(!options.targetElement || !options.animationElement) {
return false;
}
this.targetElement = options.targetElement;
this.animationElement = options.animationElement;
this.timeId = null;
this.speed = "0.3s";
}
HoverAction.prototype.addEvent = function() {
//保存this的指向
var _this = this;
_this.targetElement.addEventListener('mouseenter',function(e){
//得到鼠標(biāo)的坐標(biāo)
var point = {
x: e.pageX,
y: e.pageY
}
console.log(point);
//獲得方向
var dir = getDirection(_this.targetElement,startPoint(_this.targetElement),point);
clearTimeout(_this.timeId);
//取消過(guò)渡動(dòng)畫(huà)(防止重置動(dòng)畫(huà)載體位置時(shí)觸發(fā)過(guò)渡效果)
_this.animationElement.style.transition = "";
//得到運(yùn)動(dòng)的方向,要確定動(dòng)畫(huà)載體的開(kāi)始位置
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;
}
//異步執(zhí)行
_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,startPoint(_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,
speed: _this.speed,
changeStyle: function(){
this.style.top = top;
this.style.left = left;
}
});
},20);
},false);
}
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能有所幫助,如果有疑問(wèn)大家可以留言交流。
相關(guān)文章
12個(gè)提高JavaScript技能的概念(小結(jié))
這篇文章主要介紹了12個(gè)提高JavaScript技能的概念(小結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05
js簡(jiǎn)單實(shí)現(xiàn)圖片延遲加載的方法
這篇文章主要介紹了js簡(jiǎn)單實(shí)現(xiàn)圖片延遲加載的方法,涉及javascript針對(duì)頁(yè)面元素的遍歷與動(dòng)態(tài)設(shè)置技巧,需要的朋友可以參考下2016-07-07
javascript實(shí)現(xiàn)簡(jiǎn)易計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)簡(jiǎn)易計(jì)算器功能,實(shí)現(xiàn)四則運(yùn)算,小數(shù)點(diǎn),回退,歸0等功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-09-09
JavaScript 中Date對(duì)象的格式化代碼方法匯總
JavaScript默認(rèn)的時(shí)間格式我們一般情況下不會(huì)用,所以需要進(jìn)行格式化,下面小編給大家?guī)?lái)了三種js date對(duì)象格式化實(shí)例代碼,需要的朋友參考下吧2017-09-09

