摘要:有不對(duì)的地方,或者有更好的理解,請(qǐng)告訴我,謝謝原理以容器的中心點(diǎn)作為圓心,以高和寬的最小值作為直徑畫圓,將圓以,,,,,,,劃分為四個(gè)象限,鼠標(biāo)進(jìn)入容器時(shí)的點(diǎn)的值在這四個(gè)象限里分別對(duì)應(yīng)容器邊框的下,右,上,左。
$("#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”分別對(duì)應(yīng)著“上,右,下,左” var eventType = e.type; var dirName = new Array("上方","右側(cè)","下方","左側(cè)"); if(e.type == "mouseenter"){ $("#result").html(dirName[direction]+"進(jìn)入"); } else { $("#result").html(dirName[direction]+"離開"); } });
就這么幾行代碼,將我印象里會(huì)有一長(zhǎng)串的if else或者switch來完成的事完美的解決掉。在感到神奇之后,更多的是不解,因?yàn)榭床欢T诰W(wǎng)上搜索一番,也沒有找到有誰(shuí)來分析這個(gè)算法。于是自己研究了一下,現(xiàn)在寫下來,作為自己的一份學(xué)習(xí)筆記,也希望能夠和大家分享。
有不對(duì)的地方,或者有更好的理解,請(qǐng)告訴我,謝謝!
原理:以div容器的中心點(diǎn)作為圓心,以高和寬的最小值作為直徑畫圓,將圓以[π/4,3π/4),[3π/4,5π/4),[5π/4,7π/4),[-π/4,π/4)劃分為四個(gè)象限,鼠標(biāo)進(jìn)入容器時(shí)的點(diǎn)的atan2(y,x)值在這四個(gè)象限里分別對(duì)應(yīng)容器邊框的下,右,上,左。如下圖所示
var x = (e.pageX - this.offsetLeft - (w / 2)) * (w > h ? (h / w) : 1);
計(jì)算x坐標(biāo)值時(shí),如果點(diǎn)原來的x坐標(biāo)的絕對(duì)值大于圓的半徑值,則按 h/w 這個(gè)比例進(jìn)行縮小,使得到的點(diǎn)的位置在容器的邊界位置所對(duì)應(yīng)的象限區(qū)間里。 y 坐標(biāo)的計(jì)算也是一樣。
var direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4;
((Math.atan2(y, x) * (180 / Math.PI)將點(diǎn)的坐標(biāo)對(duì)應(yīng)的弧度值換算成角度度數(shù)值,這里加上180并非必要,只是為了使得到的0,1,2,3能夠與習(xí)慣性的上,右,下,左的位置對(duì)照,如果不加上180,得到的0,1,2,3就會(huì)分別對(duì)應(yīng)下,右,上,左。
*修正:這里加上180不是并非必要的,而是在這個(gè)算法里必須的,因?yàn)閍tan2(y,x)返回值的范圍是[-π,π],而不是我們習(xí)慣的[0,2π],負(fù)值會(huì)影響結(jié)果的正確性(比如右上和右下算出來的結(jié)果會(huì)不同),而且確實(shí)也使得得到的結(jié)果0,1,2,3的順序符合了習(xí)慣(原作者可能沒想這個(gè),只是css里總是這個(gè)順序,或許是我自己的習(xí)慣~)。
除以90,再取四舍五入值,是一個(gè)很精妙的用法,使得可以以45°為分界線。
分析完這個(gè)算法后,我內(nèi)心有些激動(dòng)。這里并沒有用到什么高深的知識(shí),即使是三角函數(shù)的基礎(chǔ)知識(shí)都可以不知道(雖然初中就學(xué)了),但是可以用這么短短的三兩行代碼,就把我腦袋里浮現(xiàn)的那一長(zhǎng)串的if else拋向云和山的彼端去,真的讓我很難抑制內(nèi)心的激動(dòng),深深的體會(huì)到算法之美,數(shù)學(xué)之美。
來源:http://sentsin.com/web/112.html
相關(guān)參考文檔:http://www.cnblogs.com/lyzg/p...
代碼參考: https://github.com/liuyunzhug...
最后感謝兩位大牛的總結(jié)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/80187.html
js實(shí)現(xiàn)點(diǎn)擊切換和自動(dòng)播放的輪播圖,其實(shí)十分簡(jiǎn)單,話不多說,我們直接看示例: 輪播圖案例 <!DOCTYPEhtml> <html> <head> <metacharset="UTF-8"> <metaname="vie...
摘要:之前總結(jié)了事件捕獲和冒泡以及阻止事件傳播,今天寫一下事件代理方面的總結(jié)事件之捕獲冒泡阻止事件傳播事件代理監(jiān)聽列表中多項(xiàng)時(shí),實(shí)現(xiàn)點(diǎn)擊控制臺(tái)打印對(duì)應(yīng)文本,如下蘋果香蕉葡萄首先想到的對(duì)每一個(gè)進(jìn)行監(jiān)聽或者使用和的區(qū)別是屬性,是方法。 之前總結(jié)了事件捕獲和冒泡以及阻止事件傳播,今天寫一下事件代理方面的總結(jié)DOM 事件之捕獲、冒泡:阻止事件傳播: 事件代理 監(jiān)聽列表中多項(xiàng) li 時(shí),實(shí)現(xiàn)點(diǎn)擊 li...
摘要:然而問題是,這個(gè)法則在導(dǎo)航條的主體是可行的但是子選單因?yàn)榍懊嫣岬降娜龑忧短讟?gòu)造圓角,已經(jīng)無法減少嵌套了,同時(shí)還得考慮到子選單也是嵌套在導(dǎo)航條里的啊。。。同理,反過來進(jìn)入子選單時(shí)自然就用來抵消達(dá)到篩選的目的。 0x1setTimeout應(yīng)用 實(shí)現(xiàn)效果:4-01setTimeout應(yīng)用 又見導(dǎo)航條,先看下css,這里用的是雪碧圖背景做出圓角的效果,雖然是經(jīng)典的方法、兼容性好,但這種代碼寫起...
摘要:這篇文章將介紹如何使用原生主要使用語(yǔ)法實(shí)現(xiàn)全屏滾動(dòng)插件,兼容手機(jī)觸屏,觸摸板優(yōu)化,支持自定義頁(yè)面動(dòng)畫,壓縮后文件只有。 這篇文章將介紹如何使用原生 JS (主要使用 ES6 語(yǔ)法)實(shí)現(xiàn)全屏滾動(dòng)插件,兼容 IE 10+、手機(jī)觸屏,Mac 觸摸板優(yōu)化,支持自定義頁(yè)面動(dòng)畫,壓縮后 gzip 文件只有 2.15KB。完整源碼在這 pure-full-page,點(diǎn)這查看 demo。 1)前面的話...
摘要:嘗試實(shí)現(xiàn)畫出一個(gè)彈射的小球很簡(jiǎn)單,那怎么用多個(gè)小球?qū)崿F(xiàn)這樣的效果呢。 本文首發(fā)于我的博客,這是我的github,歡迎star。 ??這篇博客是模仿nest.js實(shí)現(xiàn)一個(gè)demo,由簡(jiǎn)單到復(fù)雜,來一步步的實(shí)現(xiàn)它。這里是效果預(yù)覽。我的github里邊還有很多別的前端的demo,喜歡的話可以點(diǎn)個(gè)star,你的支持就是我的動(dòng)力。 從一道面試題開始 實(shí)現(xiàn)一個(gè)半徑10px的小球在500px*5...
閱讀 3052·2021-11-19 11:31
閱讀 3140·2021-09-02 15:15
閱讀 994·2019-08-29 17:22
閱讀 1064·2019-08-29 16:38
閱讀 2469·2019-08-26 13:56
閱讀 840·2019-08-26 12:16
閱讀 1441·2019-08-26 11:29
閱讀 937·2019-08-26 10:12