$("#wrap").bind("mouseenter mouseleave",function(e) { var w = $(this).width(); var h = $(this).height(); var x = (e.pageX - this.offsetLeft - (w / 2)) * (w > h ? (h / w) : 1); var y = (e.pageY - this.offsetTop - (h / 2)) * (h > w ? (w / h) : 1); var direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4; //direction的值为“0,1,2,3”分别对应着“上,右,下,左” var eventType = e.type; var dirName = new Array('上方','右侧','下方','左侧'); if(e.type == 'mouseenter'){ $("#result").html(dirName[direction]+'进入'); } else { $('#result').html(dirName[direction]+'离开'); } });
就这么几行代码,将我印象里会有一长串的if else或者switch来完成的事完美的解决掉。在感到神奇以后,更多的是不解,由于看不懂。在网上搜索一番,也没有找到有谁来分析这个算法。因而本身研究了一下,如今写下来,做为本身的一份学习笔记,也但愿可以和你们分享。css
有不对的地方,或者有更好的理解,请告诉我,谢谢!html
原理:以div容器的中心点做为圆心,以高和宽的最小值做为直径画圆,将圆以[π/4,3π/4),[3π/4,5π/4),[5π/4,7π/4),[-π/4,π/4)划分为四个象限,鼠标进入容器时的点的atan2(y,x)值在这四个象限里分别对应容器边框的下,右,上,左。以下图所示git
var x = (e.pageX - this.offsetLeft - (w / 2)) * (w > h ? (h / w) : 1);
计算x坐标值时,若是点原来的x坐标的绝对值大于圆的半径值,则按 h/w 这个比例进行缩小,使获得的点的位置在容器的边界位置所对应的象限区间里。 y 坐标的计算也是同样。github
var direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4;
((Math.atan2(y, x) * (180 / Math.PI)将点的坐标对应的弧度值换算成角度度数值,这里加上180并不是必要,只是为了使获得的0,1,2,3可以与习惯性的上,右,下,左的位置对照,若是不加上180,获得的0,1,2,3就会分别对应下,右,上,左。
*修正:这里加上180不是并不是必要的,而是在这个算法里必须的,由于atan2(y,x)返回值的范围是[-π,π],而不是咱们习惯的[0,2π],负值会影响结果的正确性(好比右上和右下算出来的结果会不一样),并且确实也使得获得的结果0,1,2,3的顺序符合了习惯(原做者可能没想这个,只是css里老是这个顺序,或许是我本身的习惯~)。web
除以90,再取四舍五入值,是一个很精妙的用法,使得能够以45°为分界线。算法
分析完这个算法后,我心里有些激动。这里并无用到什么高深的知识,即便是三角函数的基础知识均可以不知道(虽然初中就学了),可是能够用这么短短的三两行代码,就把我脑壳里浮现的那一长串的if else抛向云和山的彼端去,真的让我很难抑制心里的激动,深深的体会到算法之美,数学之美。函数
来源:http://sentsin.com/web/112.html
相关参考文档:http://www.cnblogs.com/lyzg/p...
代码参考: https://github.com/liuyunzhug...学习
最后感谢两位大牛的总结this