實(shí)現(xiàn)的效果動(dòng)圖如下
理清需求
拿到效果圖的第一步,理清下需求~
首先症汹,元素有左右上下四個(gè)方向。這邊的問題在我如何在一個(gè)元素上劃分上下左右四個(gè)區(qū)域贷腕?
然后背镇,鼠標(biāo)進(jìn)入元素和離開元素會(huì)有觸發(fā)一個(gè)事件,這個(gè)簡(jiǎn)單js就自帶了監(jiān)聽事件泽裳。
最后瞒斩,最難的是如何判斷鼠標(biāo)進(jìn)入的時(shí)候會(huì)落在我們劃分好的上下左右四個(gè)區(qū)域?
思路
-
首先我們先來(lái)劃分下四個(gè)區(qū)域涮总,一般劃分的都如下圖
區(qū)域劃分圖
圖里面有四個(gè)三角形胸囱,每個(gè)三角形代表的是一個(gè)方向,所以問題簡(jiǎn)化為如何在一個(gè)矩形里瀑梗,根據(jù)對(duì)角線劃分區(qū)域烹笔。由于元素存在坐標(biāo)系,也就是X抛丽、Y軸谤职,所以問題再次抽象成,如何得到兩條對(duì)角線的線性函數(shù)亿鲜。(初高中數(shù)學(xué)問題允蜈。)
最后的問題我們就要來(lái)搞定判斷鼠標(biāo)落點(diǎn)的問題,首先我們知道我們可以在元素的鼠標(biāo)事件中通過event得到鼠標(biāo)的pageX和pageY蒿柳,再配合元素的offsetLeft和offsetTop就可以得到鼠標(biāo)在元素中的坐標(biāo)饶套。綜合一下就變成了,我有一個(gè)坐標(biāo)其馏,且我知道對(duì)角線的函數(shù)表達(dá)式凤跑,請(qǐng)問我如何知道我這個(gè)坐標(biāo)是在函數(shù)的下面還是上面?
當(dāng)然也許描述的比較抽象叛复,我們可以類比一個(gè)例子仔引,我現(xiàn)在有一個(gè)坐標(biāo)(2,1)扔仓,有一個(gè)函數(shù)y=x,值域大于0(既y>0)咖耘,定義域大于0(既x>0)翘簇,求該坐標(biāo)在y=x的函數(shù)下面還是上面?(是不是感覺到了線性規(guī)劃得到最優(yōu)解的味道儿倒,對(duì)版保,少年,沒有錯(cuò)夫否,就是這樣彻犁。)這里我們只要把坐標(biāo)中的x值代入函數(shù),然后判斷代入的結(jié)果是否大于坐標(biāo)的y值凰慈,如果大于則在函數(shù)下面汞幢,小于則在函數(shù)上面,什么微谓?你問等于怎么辦森篷?當(dāng)然是在函數(shù)上面,該坐標(biāo)即在上面又在下面豺型,所謂薛定諤的坐標(biāo)是也(當(dāng)然是在函數(shù)上了)仲智。
然后我們是不是可以擴(kuò)展下,如果存在多個(gè)函數(shù)姻氨,再加上邏輯判斷經(jīng)常用的交集钓辆,并集是不是又有新的思維出現(xiàn)了呢?好了肴焊,這邊就不再擴(kuò)展了岩馍,下面直接上實(shí)現(xiàn)代碼吧。
實(shí)現(xiàn)代碼
注意:該demo只是簡(jiǎn)單的demo抖韩,其中有很多可以優(yōu)化的地方,比如組件化疫铜,變量?jī)?yōu)化茂浮,利用發(fā)布訂閱模式,實(shí)現(xiàn)事件聯(lián)動(dòng)
<!DOCTYPE html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css" >
.ct{
height: 100px;
width: 100px;
border:1px red solid;
}
</style>
</head>
<body>
<div class="ct" onmouseover="fun1(event);" onmouseout="fun2(event);">
</div>
<script type="text/javascript">
//當(dāng)然這樣綁定事件函數(shù)是不對(duì)的
var div=document.getElementsByTagName("div")[0];
function fun1(event){
var x=event.pageX-div.offsetLeft;//(得到鼠標(biāo)在框中的坐標(biāo))
var y=event.pageY-div.offsetTop;//(得到鼠標(biāo)在框中的坐標(biāo))
var H=div.clientHeight;
var W=div.clientWidth;
var k=Math.floor(H/W);//為了防止不能整除
//得到2個(gè)斜邊函數(shù)
//設(shè)y=ax+c
//(0,0) (width,height)其中一個(gè)斜邊過這兩點(diǎn)
//a=height/width,c=0
//y=(height/width)*x;
//(0,height) (width,0)另外一個(gè)斜邊過這兩點(diǎn)
//a=-height/width,c=height
//y=-(height/width)*x+height
if((k*x)>=y && (H-k*x)>=y){//這是判斷從上方進(jìn)入,這邊簡(jiǎn)化處理不對(duì)等于情況做特別處理
console.log("從上方進(jìn)入");
//todo
}
if((k*x)<y && (H-k*x)<y){
console.log("從下方進(jìn)入");
//todo
}
if((k*x)<y && (H-k*x)>y){
console.log("從左邊進(jìn)入");
//todo
}
if((k*x)>y && (H-k*x)<y){
console.log("從右邊進(jìn)入");
//todo
}
}
function fun2(event){
var x=event.pageX-div.offsetLeft;//(得到鼠標(biāo)在框中的坐標(biāo))
var y=event.pageY-div.offsetTop;//(得到鼠標(biāo)在框中的坐標(biāo))
var H=div.clientHeight;
var W=div.clientWidth;
var k=Math.floor(H/W);//為了防止不能整除
//得到2個(gè)斜邊函數(shù)
//設(shè)y=ax+c
//(0,0) (width,height)其中一個(gè)斜邊過這兩點(diǎn)
//a=height/width,c=0
//y=(height/width)*x;
//(0,height) (width,0)另外一個(gè)斜邊過這兩點(diǎn)
//a=-height/width,c=height
//y=-(height/width)*x+height
if((k*x)>=y && (H-k*x)>=y){//這是判斷從上方進(jìn)入,這邊簡(jiǎn)化處理不對(duì)等于情況做特別處理
console.log("從上方離開");
//todo
}
if((k*x)<y && (H-k*x)<y){
console.log("從下方離開");
//todo
}
if((k*x)<y && (H-k*x)>y){
console.log("從左邊離開");
//todo
}
if((k*x)>y && (H-k*x)<y){
console.log("從右邊離開");
//todo
}
}
</script>
</body>
</html>