摘要:碰撞檢測(cè)邊界檢測(cè)在前端游戲,以及涉及拖拽交互的場(chǎng)景應(yīng)用十分廣泛。這就涉及到碰撞檢測(cè)或者叫邊界檢測(cè)的問題了。若四邊均未發(fā)生重合,則未發(fā)生碰撞,反之則發(fā)生碰撞。目前業(yè)務(wù)有遇到碰撞需求,所以抽時(shí)間整理了下。
碰撞檢測(cè)(邊界檢測(cè))在前端游戲,以及涉及拖拽交互的場(chǎng)景應(yīng)用十分廣泛。
那么啥叫碰撞?JavaScript 又是如何檢測(cè) DOM 發(fā)生碰撞的呢?
碰撞,顧名思義,就是兩個(gè)物體碰撞在了一起,眼睛是可以直觀的觀察到碰撞的發(fā)生。但對(duì)于前端實(shí)現(xiàn),如何讓 JavaScript 代碼理解兩個(gè)獨(dú)立的“物體”(DOM)碰撞在一起呢。這就涉及到碰撞檢測(cè)(或者叫邊界檢測(cè))的問題了。
碰撞檢測(cè)的常見需求場(chǎng)景:前端常見的的碰撞,我們可以粗略的分為幾下幾類:
兩個(gè)矩形塊的碰撞:判斷任意兩個(gè)(水平)矩形的任意一邊是否有間距,從而得之兩個(gè)矩形塊有沒有發(fā)生碰撞。具體實(shí)現(xiàn)方式,可以選定一個(gè)矩形為參照物,計(jì)算另一矩形的與自己相近的邊是否發(fā)生重合現(xiàn)象。若四邊均未發(fā)生重合,則未發(fā)生碰撞,反之則發(fā)生碰撞。
圖形示例:
簡(jiǎn)單算法實(shí)現(xiàn)(非碰撞情況,else 分支就是碰撞情況):
if( domA.left > domB.right || domA.top > domB.bottom || domA.right < domB.left || domA.bottom < domB.top ) { return false // 未碰撞 } else { return true // 碰撞 }圓形與圓形的碰撞:
判斷任意兩個(gè)圓形碰撞比較簡(jiǎn)單,只需要判斷兩個(gè)圓的圓心距離是否小于兩圓半徑之和,如果小于半徑和,就可以判定兩個(gè)圓發(fā)生碰撞。
圖形示例:
簡(jiǎn)單算法實(shí)現(xiàn)
let distance = Math.sqrt(Math.pow(x1 - x2) + Math.pow(y1 - y2) ) if (distance < r1 + r2) { // r1、r2 分別為兩圓的半徑 return true // 發(fā)生碰撞 } else { return false //未發(fā)生碰撞 }圓形與矩形塊的碰撞:
圓形與矩形發(fā)生碰撞的要點(diǎn)則是要找出矩形上距離圓心最近的點(diǎn),然后通過判斷該點(diǎn)與圓心的決定是否小于圓的半徑,若小于則為碰撞。
點(diǎn)的位置,可以通過獲取矩形某一個(gè)特定的定點(diǎn)坐標(biāo)結(jié)合矩形寬高與圓的圓心進(jìn)行比較確定?;驹砼c兩個(gè)矩形碰撞相似,但是略有差異,因?yàn)閳A形有直接與矩形頂點(diǎn)碰撞的情況。
如下圖所示,與矩形碰撞的區(qū)別在于,多出了處理矩形寬高延長(zhǎng)線交叉區(qū)域的情況。當(dāng)圓心位于兩條平行邊線之間時(shí):矩形上與圓心最近的點(diǎn)為圓心垂直與矩形最近邊線的交叉點(diǎn);當(dāng)圓心位于兩條交叉邊線之間時(shí)(如下圖斜線區(qū)域),與圓心最近的點(diǎn)則是矩形交叉邊線的頂點(diǎn):
簡(jiǎn)單算法實(shí)現(xiàn)(B 圓只是做輔助說明)
// 假設(shè) 矩形為 Box, 圓的半徑為 R let distance if (x1 < Box.left && y1 > Box.top && y1 < Box.bottom) { // 位于上圖中 圓 A 的 位置 distance = Box.left - x1 } else if ( x1 > Box.Right && y1 < Box.top ) { // 位于 上圖中 圓 B 的位置 distance = Math.sqrt(Math.pow(x1 - Box.right) + Math.pow(y1 - Box.top)) } // 其他幾種情況類似...按著順/逆時(shí)針的順序,總共八個(gè)區(qū)域就能全覆蓋 if (distance < R) { return true // 碰撞 } else { return false // 未碰撞 }
還有一種涉及到多 DOM 碰撞的情況,一般業(yè)務(wù)需求是動(dòng)態(tài)生成 DOM,占位,移動(dòng),然后再生成新 DOM,使他們不可重疊。通過查資料發(fā)現(xiàn) 地圖碰撞 算法比較適合這樣的場(chǎng)景。
地圖碰撞算法地圖碰撞算法 主要是應(yīng)用了矩陣的思想。即將拖拽區(qū)域進(jìn)行數(shù)據(jù)化分割,劃分成一個(gè)假想的數(shù)據(jù)地圖,每一個(gè)小塊算是一個(gè)獨(dú)立的位置格子,通過標(biāo)記狀態(tài)來確定小格子是否被占用。然后應(yīng)用最簡(jiǎn)單的 矩形碰撞 來判定拖動(dòng)的 DOM 是否與格子發(fā)生碰撞,發(fā)生則將格子狀態(tài)改為 1,未被占用則標(biāo)記為 0。只有未被占用的格子可以被占用,占用的格子,釋放后標(biāo)記為 0。這種狀態(tài)管理的方式,很適合結(jié)合 React、Vue 等前端框架做一些拖拽、碰撞的復(fù)雜業(yè)務(wù)交互。
圖形示例:
簡(jiǎn)單思路實(shí)現(xiàn)
// 區(qū)域是否可用 標(biāo)記 矩陣 let map = [ [0, 1, 0, 0], [0, 0, 0, 0] ] // 設(shè)置初始位置 let NewDom = { left: 0, top: 0} // 判斷是否可安置 ...
以上是比較主流的幾種碰撞情況,以及主要的思路實(shí)現(xiàn)。目前業(yè)務(wù)有遇到碰撞需求,所以抽時(shí)間整理了下。圓形和矩形碰撞的情況感覺還可以優(yōu)化下,如果有好的思路,可以互相學(xué)習(xí)下。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/100245.html
摘要:碰撞檢測(cè)邊界檢測(cè)在前端游戲,以及涉及拖拽交互的場(chǎng)景應(yīng)用十分廣泛。這就涉及到碰撞檢測(cè)或者叫邊界檢測(cè)的問題了。若四邊均未發(fā)生重合,則未發(fā)生碰撞,反之則發(fā)生碰撞。目前業(yè)務(wù)有遇到碰撞需求,所以抽時(shí)間整理了下。 碰撞檢測(cè)(邊界檢測(cè))在前端游戲,以及涉及拖拽交互的場(chǎng)景應(yīng)用十分廣泛。 那么啥叫碰撞?JavaScript 又是如何檢測(cè) DOM 發(fā)生碰撞的呢? 碰撞,顧名思義,就是兩個(gè)物體碰撞在了一起,...
摘要:通用算法概念模型圓形與矩形之間的碰撞核心理念通過找出矩形上離圓心最近的點(diǎn),然后通過判斷該點(diǎn)與圓心的距離是否小于圓的半徑,若小于則為碰撞。 碰撞檢測(cè)在前端游戲,設(shè)計(jì)拖拽的實(shí)用業(yè)務(wù)等領(lǐng)域的應(yīng)用場(chǎng)景非常廣泛,今天我們就在這里對(duì)于前端JavaScript如何實(shí)現(xiàn)碰撞檢測(cè)算法進(jìn)行一個(gè)原理上的探討,讓大家能夠明白如何實(shí)現(xiàn)碰撞以及碰撞的理念是什么:1.矩形與矩形間的碰撞核心理念判斷任意兩個(gè)(無旋轉(zhuǎn))...
摘要:前言啃了這么長(zhǎng)時(shí)間,基本上已經(jīng)把某數(shù)的套路摸了個(gè)八九不離十,不愧是中國(guó)反爬界的集大成者,感覺收獲滿滿,這里就簡(jiǎn)單記錄一下分析成果。注意某數(shù)在不同的網(wǎng)站上有不同的版本,其流程也略有不同,這里的流程不一定適用于其它網(wǎng)站。 showImg(https://segmentfault.com/img/remote/1460000018765904); 前言 啃了這么長(zhǎng)時(shí)間,基本上已經(jīng)把某數(shù)的套路...
閱讀 1830·2021-09-22 15:54
閱讀 2941·2021-09-01 10:42
閱讀 3456·2019-08-30 15:56
閱讀 1450·2019-08-29 18:46
閱讀 2482·2019-08-29 10:57
閱讀 2722·2019-08-28 17:57
閱讀 3673·2019-08-23 18:14
閱讀 847·2019-08-23 17:03