咱们从一个小例子做引子,见微知著好吧!
假如说现在有这样一道题,网页上有一个正方形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
这样是不是方位就出来了?那具体代码得怎样实现呢?
先看看下面这个:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <style> 7 html,body,div{margin:0;padding:0} 8 .test{ 9 width:200px; 10 height:200px; 11 margin: 100px auto 0; 12 box-shadow:0 0 5px #000; 13 } 14 </style> 15 <script> 16 window.onload=function(){ 17 var oBox=document.getElementsByClassName('test')[0], 18 centerX=oBox.offsetLeft+oBox.offsetWidth/2, 19 centerY=oBox.offsetTop+oBox.offsetHeight/2; 20 21 // console.log(centerX);//中心点 22 // console.log(centerY); 23 24 var direction; 25 26 oBox.addEventListener('mouseenter',function(e){ 27 28 e = e || window.event; 29 var x=e.clientX-centerX, 30 y=e.clientY-centerY; 31 32 //根据反正切求角度:(arctan(y/x)/π) * 180 33 // var deg=-Math.atan2(y,x) * (180/Math.PI);//看看前面有个负号,为什么呢?因为我们浏览器的y轴正向是向下的与我们 34 35 // 的普通坐标轴相反 36 // console.log(deg);//看看deg是不是我们第一个的那种角度呢?这里只是很简单的用一个反正切来得到角度 37 // 38 // //这里我分成一步步写哈 39 // var deg1=deg+180;//是不是加了180? 40 // 41 // var deg2=deg1/90;//是不是除以90? 42 // 43 // var deg3=Math.round(deg2);//是不是四舍五入? 44 // 45 // var degValue=deg3%4; 46 // 47 // console.log(degValue);//可以鼠标移动看看哈,看是否有上对应3,左对应0等等的情况 48 49 var degValue=Math.round((-Math.atan2(y,x) * (180/Math.PI)+180)/90)%4; 50 51 switch(degValue){ 52 case 0 : direction = "left"; break; 53 case 1 : direction = "bottom"; break; 54 case 2 : direction = "right"; break; 55 case 3 : direction = "top"; break; 56 } 57 console.log(direction); 58 59 }) 60 61 } 62 </script> 63 </head> 64 <body> 65 <div class="test"></div> 66 </body> 67 </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的请随便搜索个版本自行引入。
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>初步测试</title> 6 <style> 7 html,body,div,ul,li{margin:0;padding:0;} 8 li{list-style:none} 9 .list{ 10 width:880px; 11 height:400px; 12 margin:100px auto 0; 13 box-shadow:0 0 5px #000; 14 } 15 li{ 16 margin:10px; 17 width:200px; 18 height:180px; 19 float:left; 20 perspective:1000px; 21 position:relative; 22 cursor: pointer; 23 } 24 .liBox{ 25 width:100%; 26 height:100%; 27 position:absolute; 28 transform-origin:50% 50% -100px; 29 animation: 200ms ease-out 0ms 1 normal forwards; 30 transform-style: preserve-3d; 31 } 32 .pic,.words{ 33 position:absolute; 34 width:100%; 35 height:100%; 36 } 37 .pic{background:skyblue} 38 .words{background: #a9ebaa;visibility: hidden} 39 40 /*当鼠标进入li的时候呢,里面的picture和words两个元素层呢迅速做变轨*/ 41 .words-top{ 42 transform:rotateX(90deg) translate3d(0,-50%,90px); 43 } 44 .words-bottom{ 45 transform: rotateX(-90deg) translate3d(0,50%,90px); 46 } 47 .words-left{ 48 transform: rotateY(-90deg) translate3d(-50%,0,100px); 49 } 50 .words-right{ 51 transform: rotateY(90deg) translate3d(50%,0,100px); 52 } 53 54 55 /*上*/ 56 .in-top{ 57 animation-name: in-top; 58 animation-play-state: running; 59 } 60 .out-top{ 61 animation-name: out-top; 62 animation-play-state: running; 63 } 64 65 /*下*/ 66 .in-bottom{ 67 animation-name: in-bottom; 68 animation-play-state: running; 69 } 70 .out-bottom{ 71 animation-name: out-bottom; 72 animation-play-state: running; 73 } 74 75 /*左*/ 76 .in-left{ 77 animation-name: in-left; 78 animation-play-state: running; 79 } 80 .out-left{ 81 animation-name: out-left; 82 animation-play-state: running; 83 } 84 85 /*右*/ 86 .in-right{ 87 animation-name: in-right; 88 animation-play-state: running; 89 } 90 .out-right{ 91 animation-name: out-right; 92 animation-play-state: running; 93 } 94 95 /*上*/ 96 @keyframes in-top { 97 from{transform:rotate3d(0,0,0,0deg)} 98 to{transform:rotate3d(-1,0,0,90deg)} 99 } 100 @keyframes out-top { 101 from{transform: rotate3d(-1,0,0,90deg)} 102 to{transform:rotate3d(0,0,0,0deg)} 103 } 104 /*下*/ 105 @keyframes in-bottom { 106 from{transform:rotate3d(0,0,0,0deg)} 107 to{transform:rotate3d(1,0,0,90deg)} 108 } 109 @keyframes out-bottom { 110 from{transform: rotate3d(1,0,0,90deg)} 111 to{transform:rotate3d(0,0,0,0deg)} 112 } 113 /*左*/ 114 @keyframes in-left { 115 from{transform:rotate3d(0,0,0,0deg)} 116 to{transform:rotate3d(0,1,0,90deg)} 117 } 118 @keyframes out-left { 119 from{transform: rotate3d(0,1,0,90deg)} 120 to{transform:rotate3d(0,0,0,0deg)} 121 } 122 /*右*/ 123 @keyframes in-right { 124 from{transform:rotate3d(0,0,0,0deg)} 125 to{transform:rotate3d(0,-1,0,90deg)} 126 } 127 @keyframes out-right { 128 from{transform: rotate3d(0,-1,0,90deg)} 129 to{transform:rotate3d(0,0,0,0deg)} 130 } 131 132 </style> 133 <script src="../dist/js/jquery-3.3.1.min.js" type="text/javascript"></script> 134 <script> 135 $(function(){ 136 137 var $list=$('.list'), 138 $li=$list.find('li'); 139 140 var directionClass,//方向类名 141 offset; //旋转中心偏移值 142 143 144 $li.on('mouseenter',function(e){ 145 directionClass=getDirection(e,$(this)); 146 147 (directionClass === "left" || directionClass === "right") ? offset =$(this).width()/2 : offset = $(this).height()/2; 148 $(this).find('.words').css("visibility","visible").removeClass().addClass('words words-'+directionClass); 149 $(this).children('div').removeClass().addClass('liBox'); 150 $(this).children('div').addClass("in-"+directionClass); 151 $(this).children('.liBox').css("transform-origin","50% 50% -"+offset+"px"); 152 }); 153 $li.on("mouseleave",function(){ 154 $(this).children('div').addClass("out-"+directionClass); 155 }); 156 157 var getDirection=function(e,obj){ 158 159 e = e || window.event; 160 161 var direction; 162 //obj中心点与边角点(任意取一个都行) 163 var cx = obj.width()/2 + obj.offset().left, 164 cy = obj.height()/2 + obj.offset().top; 165 166 var abs=Math.abs((e.pageY-cy)/(e.pageX-cx))-Math.abs(obj.width()/obj.height()); 167 abs > 0 ? (e.pageY > cy ? direction = "bottom" : direction = "top") : (e.pageX > cx ? direction = "right" : direction = "left"); 168 169 return direction; 170 } 171 172 }); 173 </script> 174 </head> 175 <body> 176 <div class="list"> 177 <ul> 178 <li> 179 <div class="liBox"> 180 <div class="pic"></div> 181 <div class="words"></div> 182 </div> 183 </li> 184 <li> 185 <div class="liBox"> 186 <div class="pic"></div> 187 <div class="words"></div> 188 </div> 189 </li> 190 <li> 191 <div class="liBox"> 192 <div class="pic"></div> 193 <div class="words"></div> 194 </div> 195 </li> 196 <li> 197 <div class="liBox"> 198 <div class="pic"></div> 199 <div class="words"></div> 200 </div> 201 </li> 202 <li> 203 <div class="liBox"> 204 <div class="pic"></div> 205 <div class="words"></div> 206 </div> 207 </li> 208 <li> 209 <div class="liBox"> 210 <div class="pic"></div> 211 <div class="words"></div> 212 </div> 213 </li> 214 <li> 215 <div class="liBox"> 216 <div class="pic"></div> 217 <div class="words"></div> 218 </div> 219 </li> 220 <li> 221 <div class="liBox"> 222 <div class="pic"></div> 223 <div class="words"></div> 224 </div> 225 </li> 226 </ul> 227 </div> 228 </body> 229 </html>
总结一下:
前端中的数学呢?其实不难,仅仅只是一些二维平面的运算或是一些三维几何运算,不用去怕它,以后有什么新数学方法也会放在这后面,真的挺有意思的,对吧!