咱來談?wù)勄岸酥械臄?shù)學(xué),當(dāng)然啦,順便也來寫點(diǎn)好玩的東西!
咱们从一个小例子做引子,见微知著好吧!
假如说现在有这样一道题,网页上有一个正方形div,大致的外观差不多是这样:
然后呢,鼠标从左移进去的时候呢,打印一个"左"字,右边移入呢,打印一个"右"字,上边,下边移入呢,也是一样,那怎样判断鼠标在这个div的方位呢?
咋看起来好像蛮简单的对吧?不就是获取鼠标位置,再鼠标的x小于这个div的左边距的时候是左,大于左边距+宽度的时候是右,小于上边距的时候是上,大于上边距+高度的时候是下,再用个鼠标移入去触发对吧?好像是这样,但是呢?其实你真这样去做你会发现走不通,为什么呢?鼠标的移入事件浏览器实际上是怎样判断的呢?无非是鼠标的位置在这个div之内的第一个落脚点,对吧,得之内,也就是说,之外的是行不通的。而且,假如说,我不是一个,而是5个,10个,甚至100个呢?再这样去想就稍微有点把自己给坑了对吧?
那得怎样去判断呢?(先看下下面这张图)
我的思路呢是按角度来,可以先想想,假如说以正方形的中心点为圆点画一个坐标轴的话,那我们这个上下左右的角度会是怎样?
就是上面这样对吧?有负的咱不好理解,全部加个180,变成这样:
然后你发现了吗?上下左右都间隔90°,是吧,咱再来除以90,然后就变成了:
然后呢?你发现2.5~3.5的四舍五入变成什么呢? 3对吧?
好了,发现规律了,然后呢变成这样:
上:3 左:4或者0 下:1 右:2
你说左有点问题啊,嗯是的,那如果把所有的值再来余4呢?看看,是不是很酷,变成了:
左:0 下:1 右:2 上:3
这样是不是方位就出来了?那具体代码得怎样实现呢?
先看看下面这个:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
html,body,div{margin:0;padding:0}
.test{
width:200px;
height:200px;
margin: 100px auto 0;
box-shadow:0 0 5px #000;
}
</style>
<script>
window.=function(){
var oBox=document.getElementsByClassName('test')[0],
centerX=oBox.offsetLeft+oBox.offsetWidth/2,
centerY=oBox.offsetTop+oBox.offsetHeight/2;
// console.log(centerX);//中心点
// console.log(centerY);
var direction;
oBox.addEventListener('mouseenter',function(e){
e = e || window.event;
var x=e.clientX-centerX,
y=e.clientY-centerY;
//根据反正切求角度:(arctan(y/x)/π) * 180
// var deg=-Math.atan2(y,x) * (180/Math.PI);//看看前面有个负号,为什么呢?因为我们浏览器的y轴正向是向下的与我们
// 的普通坐标轴相反
// console.log(deg);//看看deg是不是我们第一个的那种角度呢?这里只是很简单的用一个反正切来得到角度
//
// //这里我分成一步步写哈
// var deg1=deg+180;//是不是加了180?
//
// var deg2=deg1/90;//是不是除以90?
//
// var deg3=Math.round(deg2);//是不是四舍五入?
//
// var degValue=deg3%4;
//
// console.log(degValue);//可以鼠标移动看看哈,看是否有上对应3,左对应0等等的情况
var degValue=Math.round((-Math.atan2(y,x) * (180/Math.PI)+180)/90)%4;
switch(degValue){
case 0 : direction = "left"; break;
case 1 : direction = "bottom"; break;
case 2 : direction = "right"; break;
case 3 : direction = "top"; break;
}
console.log(direction);
})
}
</script>
</head>
<body>
<div class="test"></div>
</body>
</html>上面的代码可以看到效果,而实际上写了那么多,最终最终有用的其实就红色框框这么一句:
是不是很简单?但是呢?还有个问题?什么问题?如果元素不是正方形那可得怎么搞?不是90度了啊?你原来这个不得全部推翻吗?不不不,上面是我们完成下面的思维基石;
那得怎么分析呢?先看看:
看看上面:是不是从上侧移动时的鼠标坐标点的与原点的连线是不是更陡峭?上下都是比较陡峭的对吧?或者说他们的角度绝对值更大一些,是吧?左右呢?则是偏缓一些,或者说角度绝对值更小一些对吧?
这样,它就促使我们这样去想:
上,下:|y1/x1| > 边角点的 |y0/x0|
左,右:|y1/x1| < 边角点的 |y0/x0|
你说那上下怎么办呢?别急,上边移入的y1是不是大于0的?错,是小于0哈,再次强调一边,浏览器的y轴是从上到下,也就是说,当在上面区域,你鼠标的点的y值<中心点的y值,所以呢?得出了一个结论:(在上面的条件下)
上:y1<0 下:y1>0 左:x1<0 右:x1>0
你说好像写成代码还挺难的样子,是吧?我贴几句话你看看哈,难不难你就心中有数了。
真正起作用的仅有中间的3行代码,难吗?
既然有个比较通用的,比较靠谱的,对吧?那咱就来写一写代码,当然啦,总是弹出上啊,左啊右啊的,没意思,咱加点效果,好吧?
当然了,下面这个代码呢,我就仅仅写了上边的哈,记住上边移入的时候会有完整效果,其他方向呢,也有,但是呢,没上边的好看,为什么要这样呢?因为你看了这么多对吧?总得自己练一练,不然是没有效果的,代码我就贴下边哈,自己尝试尝试,把左下跟右的效果补全。
jQuery的请随便搜索个版本自行引入。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>初步测试</title>
<style>
html,body,div,ul,li{margin:0;padding:0;}
li{list-style:none}
.list{
width:800px;
height:440px;
margin:100px auto 0;
box-shadow:0 0 5px #000;
}
li{
margin:10px;
width:180px;
height:200px;
float:left;
perspective:1000px;
position:relative;
}
.liBox{
width:100%;
height:100%;
position:absolute;
transform-origin:50% 50% -100px;
animation: 250ms ease-out 0ms 1 normal forwards;
transform-style: preserve-3d;
}
.pic,.words{
position:absolute;
width:100%;
height:100%;
/*transition:0.5s;*/
}
.pic{background:skyblue}
.words{background: #a9ebaa;visibility: hidden}
/*当鼠标进入li的时候呢,里面的picture和words两个元素层呢迅速做变轨*/
.wordsTop{
transform:rotateX(90deg) translate3d(0,-50%,100px);
}
/*上*/
.in-top{
animation-name: in-top;
animation-play-state: running;
}
.out-top{
animation-name: out-top;
animation-play-state: running;
}
/*下*/
.in-bottom{
animation-name: in-bottom;
animation-play-state: running;
}
.out-bottom{
animation-name: out-bottom;
animation-play-state: running;
}
/*左*/
.in-left{
animation-name: in-left;
animation-play-state: running;
}
.out-left{
animation-name: out-left;
animation-play-state: running;
}
/*右*/
.in-right{
animation-name: in-right;
animation-play-state: running;
}
.out-right{
animation-name: out-right;
animation-play-state: running;
}
/*上*/
@keyframes in-top {
from{transform:rotate3d(0,0,0,0deg)}
to{transform:rotate3d(-1,0,0,90deg)}
}
@keyframes out-top {
from{transform: rotate3d(-1,0,0,90deg)}
to{transform:rotate3d(0,0,0,0deg)}
}
/*下*/
@keyframes in-bottom {
from{transform:rotate3d(0,0,0,0deg)}
to{transform:rotate3d(1,0,0,90deg)}
}
@keyframes out-bottom {
from{transform: rotate3d(1,0,0,90deg)}
to{transform:rotate3d(0,0,0,0deg)}
}
/*左*/
@keyframes in-left {
from{transform:rotate3d(0,0,0,0deg)}
to{transform:rotate3d(0,1,0,90deg)}
}
@keyframes out-left {
from{transform: rotate3d(0,1,0,90deg)}
to{transform:rotate3d(0,0,0,0deg)}
}
/*右*/
@keyframes in-right {
from{transform:rotate3d(0,0,0,0deg)}
to{transform:rotate3d(0,-1,0,90deg)}
}
@keyframes out-right {
from{transform: rotate3d(0,-1,0,90deg)}
to{transform:rotate3d(0,0,0,0deg)}
}
</style>
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="dist/js/jquery-3.3.1.min.js" type="text/javascript"></script>
<script>
$(function(){
var $list=$('.list'),
$li=$list.find('li');
var flag,directionClass;//标志位跟方向类名
$li.on('mouseenter',function(e){
e = e || window.event;
var cx=$(this).width()/2+$(this).offset().left,//中心点x轴坐标 cx(centerX缩写)
cy=$(this).height()/2+$(this).offset().top,//中心点y轴坐标
bx=$(this).width()+$(this).offset().left,//同时由于元素不一定是正方形,需要获取边角的点坐标
by=$(this).height()+$(this).offset().top;//这里取的是右下角 bx(borderX缩写)
// console.log("cx:"+cx+"\ncy:"+cy);
//鼠标点与中心点的连线,类似于初中数学x1-x2
var spaceX=e.pageX-cx,
spaceY=e.pageY-cy;
//边角点与中心连线,
var borderX=bx-cx,
borderY=by-cy;
//判断方向
var abs=Math.abs(spaceY/spaceX)-Math.abs(borderY/borderX);
console.log("abs"+abs);
abs>0?(spaceY>0?flag=2:flag=0):(spaceX>0?flag=1:flag=3);
switch(flag){
case 0 : directionClass="top";break;
case 1 : directionClass="right";break;
case 2 : directionClass="bottom";break;
case 3 : directionClass="left";break;
}
console.log(directionClass);//看看这个打印哦,看看鼠标从不同方位进入的时候打印了什么?不知道控制台的请按F12即可
$(this).find('.words').css("visibility","visible").addClass('wordsTop');
$(this).children('div').removeClass().addClass('liBox');
$(this).children('div').addClass("in-"+directionClass);
})
})
</script>
</head>
<body>
<div class="list">
<ul>
<li>
<div class="liBox">
<div class="pic"></div>
<div class="words"></div>
</div>
</li>
<li>
<div class="liBox">
<div class="pic"></div>
<div class="words"></div>
</div>
</li>
<li>
<div class="liBox">
<div class="pic"></div>
<div class="words"></div>
</div>
</li>
<li>
<div class="liBox">
<div class="pic"></div>
<div class="words"></div>
</div>
</li>
<li>
<div class="liBox">
<div class="pic"></div>
<div class="words"></div>
</div>
</li>
<li>
<div class="liBox">
<div class="pic"></div>
<div class="words"></div>
</div>
</li>
<li>
<div class="liBox">
<div class="pic"></div>
<div class="words"></div>
</div>
</li>
<li>
<div class="liBox">
<div class="pic"></div>
<div class="words"></div>
</div>
</li>
</ul>
</div>
</body>
</html>(原创首发于慕课网)
共同學(xué)習(xí),寫下你的評(píng)論
評(píng)論加載中...
作者其他優(yōu)質(zhì)文章







