$("#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