canvas判斷點是否在路徑內

方帥發表於2021-04-15

應用場景

我們的專案中有個功能是,canvas上的某個圖片選中後可以再這個圖片上用滑鼠拖拽繪製畫筆線條。

當然繪製的邊界要控制在圖片大小範圍內的,那麼滑鼠是可以隨意動的,怎麼能控制只在圖片上的時候才繪製呢?

Canvas 2D API 有直接提供的方法:CanvasRenderingContext2D.isPointInPath() 用於判斷在當前路徑中是否包含檢測點的方法

isPointInPath介紹

語法:

boolean ctx.isPointInPath(x, y);
boolean ctx.isPointInPath(x, y, fillRule);

boolean ctx.isPointInPath(path, x, y);
boolean ctx.isPointInPath(path, x, y, fillRule);

 

引數:

x 檢測點的X座標  
y 檢測點的Y座標  
fillRule 用來決定點在路徑內還是在路徑外的演算法。
  • "nonzero": 非零環繞規則,預設值。
  • "evenodd": 奇偶環繞原則 。

返回值:

一個Boolean值,當檢測點包含在當前或指定的路徑內,返回 true;否則返回 false。

 非零環繞原則

規則是從點引出任意一條射線,與路徑交點結果計算,如果計數不為0,那麼此點就在路徑範圍裡面,在呼叫fill()方法時,瀏覽器就會對其進行填充。如果最終值是0,那麼此區域就不在路徑範圍內,瀏覽器就不會對其進行填充。

 

 首先,我們得給圖形確定一條路徑,只要“一筆畫”並且“不走重複路線”就可以了。如圖,標出的是其中的一種路徑方向。我們先假定路徑的正方向(逆時針)為1,那麼反方向(順時針)就是其相反數-1。(整個定義可以反過來的,正方向為順時針,反方向為逆時針)

接下來,我們就來判斷了。

點P1中引出的任意一條射線L1,與一條正方向路徑相交,那麼我們就給計數器+1,結果為+1,所以點P1在外面。

點P2中引出的任意一條射線L2,與兩條子路徑的正方向相交,計數器+2,結果為+2,所以點P2在外面。

點P3中引出的任意一條射線L3,與兩條子路徑相交,但是其中有一條的反方向,計數器+1-1,結果為0,所以點P3在裡面。

點P4中引出的任意一條射線L4,與一條子路徑相交,路徑為反方向,計數器-1,結果為-1,所以點P4在外面。

只要結果不為0,判斷的點就在區域的外面。結果為0,點在區域裡面(綠色區域)

奇偶環繞原則

奇偶環繞原則理解為:

平面內的任何一點P,引出一條射線,注意不要經過多邊形的頂點,如果射線與多邊形的交點的個數為奇數,則點P在多邊形的內部;如果交點的個數為偶數,則點P在多邊形的外部。

 

 我們用這個方法判斷的結果是:

P1,P4與路徑交點為1,所以是在裡面

P2,P3與路徑交點為2,所以實在外面



參考:https://www.jianshu.com/p/ce72c4402f7a

相關文章