前端小功能: 繪制多邊形,並判斷某個點是否在區域內


canvas 繪制不規則多邊形,包涵里面的元素不能超出多邊形。

canvas繪制多邊形,並且判斷某個點是否在區域內。

涉及canvas畫點,畫線,成面。

x,y坐標系,斜率,js拖拽等。

斜率: k=(y2-y1)/(x2-x1);

canvas畫點,畫線,成面:

  // 繪制連接的折線
  this.cxt.beginPath();
  this.cxt.strokeStyle='#666';
  this.cxt.lineWidth = 1;
  this.cxt.moveTo(maxXyArr[0].x,maxXyArr[0].y );
  for(let i=1,len=maxXyArr.length;i<len;i++){
      this.cxt.lineTo(maxXyArr[i].x,maxXyArr[i].y);
  }
  this.cxt.closePath(); //雖然我們只繪制了兩條線段,但是closePath會closePath,仍然是一個3角形
  this.cxt.stroke(); // 描邊。stroke不會自動closePath()            
maxXyArr,就是坐標點。錄入三個以上坐標就能成面。
demo坐標例子maxXyArr:[{x:100,y:100},{x:100,y:400},{x:400,y:400},{x:400,y:100}],
當然這個是一個規矩的四邊形,判斷某個點是否在區域內,可以是任意圖形。

判斷某個點在多邊形內部

問題假設:有一個點P,有一個多邊形A,我們要判斷A是否包含P。

基礎知識–光線投射法

原理:

1、從點P出發,任意引一條射線(模擬光線)。

2、記錄該條射線與多邊形A的邊相交點的個數。

3、判斷交點的個數,若為偶數表示在圖形外,若為奇數表示在圖像內。

光線投射法【升級版】

原理:

1、從點P出發,任意引一條射線(模擬光線)。

2、該條射線與多邊形A的邊相交時,若射線從邊的左側貫穿記錄leftCount加1,若射線從邊的右側貫穿記錄rightCount加1。

3、若leftCount-rightCount等於0表示在圖形外部,若不等於0表示圖形內部。

/**
* @param  dot {{x,y}} 需要判斷的點
* @param  coordinates {{x,y}[]} 多邊形點坐標的數組,為保證圖形能夠閉合,起點和終點必須相等。
*        比如三角形需要四個點表示,第一個點和最后一個點必須相同。 
* @param noneZeroMode 對不規則圖形進行判斷
*/ function judge(dot,coordinates,noneZeroMode) {   // 默認啟動none zero mode   noneZeroMode=noneZeroMode||1;   var x = dot.x,y=dot.y;   var crossNum = 0; // 點在線段的左側數目 var leftCount = 0; // 點在線段的右側數目 var rightCount = 0; for(var i=0;i<coordinates.length-1;i++){ var start = coordinates[i]; var end = coordinates[i+1]; // 起點、終點斜率不存在的情況 if(start.x===end.x) { // 因為射線向右水平,此處說明不相交 if(x>start.x) continue; // 從左側貫穿 if((end.y>start.y&&y>=start.y && y<=end.y)){ leftCount++; crossNum++; } // 從右側貫穿 if((end.y<start.y&&y>=end.y && y<=start.y)) { rightCount++; crossNum++; } continue; } // 斜率存在的情況,計算斜率 var k=(end.y-start.y)/(end.x-start.x); // 交點的x坐標 var x0 = (y-start.y)/k+start.x; // 因為射線向右水平,此處說明不相交 if(x>x0) continue; if((end.x>start.x&&x0>=start.x && x0<=end.x)){ crossNum++; if(k>=0) leftCount++; else rightCount++; } if((end.x<start.x&&x0>=end.x && x0<=start.x)) { crossNum++; if(k>=0) rightCount++; else leftCount++; } } return noneZeroMode===1?leftCount-rightCount!==0:crossNum%2===1; },

通過獲取點擊的坐標點進行判斷,於canvas畫矩形

let dot = {x: e.offsetX, y: e.offsetY}
let maxArray = JSON.parse(JSON.stringify(maxXyArr))
maxArray.push(coordinates[0])
let flag = judge(dot,maxArray)
console.log(flag)

完成。

這樣的不規則圖形UI才能很方便的響應舞台的事件。

 

沒有終點,沒有彼岸,堅持就好,願歲月如初


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM