簡體   English   中英

如何使用JavaScript中的for循環繪制完整的多邊形?

[英]How do I draw a complete polygon using a for loop in Javascript?

因此,我試圖利用HTML的Canvas繪制凸多邊形。

在下面的代碼中,t2是一個點數組(我已經聲明了該類,代碼可以正常工作,並且一切,getX()返回X,getY()返回Y。)

繪圖功能一直有效,直到到達for循環之后的代碼為止。 我想畫一條連接第一個點和最后一個點的線,但是由於某種原因,它根本沒有執行。

var i;
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
for(i = 0; i<t2.length-2; i++){
    var t3 = t2[i];
    var t4 = t2[i+1];


    ctx.moveTo(t3.getX(), t3.getY());
    ctx.lineTo(t4.getX(), t4.getY());
    ctx.stroke();
}
var t5 = t2[t2.length-1];
var t6 = t2[0];



ctx.moveTo(t5.getX(), t5.getY());
ctx.lineTo(t6.getX(), t6.getY());
ctx.stroke();

畫布應該顯示一條連接點t5和t6的線,但是什么也沒有發生。 for循環中的所有內容均有效,但之后的所有內容均無效。

closePath()是您的朋友在這里...請參閱: https : //developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/closePath

如果沒有可行的示例,那么您將無法對您的需求進行最佳估計。

let c = document.getElementById("myCanvas");
let ctx = c.getContext("2d");
//Start the path.
ctx.beginPath();
//Move to the initial vector.
ctx.moveTo(t2[0].getX(), t2[0].getY());
//Loop through the rest of the vectors skipping the first one.
for(let i = 1; i < t2.length; i++){
    //Add a line to the path. This always originates from the previous lineTo end vector.
    ctx.lineTo(t2[i].getX(), t2[i].getY());
}
//closePath() attempts to draw a line from the last vector to the first vector in the current path.
ctx.closePath();
//Stroke.
ctx.stroke();

該代碼正在做一些奇怪的事情。

  1. 它在循環內稱為stroke 這意味着它將繪制第一條線,然后繪制第一條和第二條線,然后繪制第一條,第二條和第三條線,依此類推...

    如果要分別繪制每條線,則需要在每次調用stroke之后調用beginPath 如果只想繪制所有線條,則應該在末尾僅調用一次描邊。

  2. 每個段都使用moveTo / lineTo。 這不是制作多邊形,而是繪制N條線段。 不同之處在於,如果您調用fill而不是stroke,則它將失敗,因為代碼沒有制作多邊形,而是制作了單獨的線條。

  3. 您不需要第一個moveTo 調用beginPath之后,對lineTo的首次調用將自動為moveTo (感謝@Kaiido)

  4. 它沒有將最后一點與第一點聯系起來。

    您可以使用closePath做到這一點

這是工作示例

 class Vec2 { constructor(x, y) { this.x = x; this.y = y; } getX() { return this.x; } getY() { return this.y; } } const t2 = [ new Vec2(10, 10), new Vec2(100, 10), new Vec2(100, 100), new Vec2(10, 100), ]; const c = document.getElementById("myCanvas"); const ctx = c.getContext("2d"); ctx.beginPath(); for(let i = 0; i < t2.length; ++i){ const t3 = t2[i]; ctx.lineTo(t3.getX(), t3.getY()); } ctx.closePath(); ctx.stroke(); 
 <canvas id="myCanvas"></canvas> 

但是,如果代碼更像JavaScript,那么有些事情可能會更簡單。

首先,如果我們使Vec2將x和y保留在數組中,並使用get然后返回該數組,而不是

ctx.lineTo(t3.getX(), t3.getY());

我們可以做

ctx.lineTo(...t3.get());

現在,代碼正在使用this.value存儲2個值,如果我們仍然需要它們,可以為x和y添加getter。 然后t3.getX()變成t3.x

另一個是您可以使用for ... of代替循環的計數器

for (const point of t2) {
   ctx.lineTo(...point.get());
}

只是一些建議。

 class Vec2 { constructor(x, y) { this.value = [x, y]; } get() { return this.value; } get x() { return this.value[0]; } set x(v) { this.value[0] = v; } get y() { return this.value[1]; } set y(v) { this.value[1] = v; } } const t2 = [ new Vec2(10, 10), new Vec2(100, 10), new Vec2(100, 100), new Vec2(10, 100), ]; const c = document.getElementById("myCanvas"); const ctx = c.getContext("2d"); ctx.beginPath(); for (const point of t2) { ctx.lineTo(...point.get()); } ctx.closePath(); ctx.stroke(); 
 <canvas id="myCanvas"></canvas> 

另外,也可以使用forEach循環來代替for ... of循環

    t2.forEach(point => ctx.lineTo(...point.get()));

 class Vec2 { constructor(x, y) { this.value = [x, y]; } get() { return this.value; } get x() { return this.value[0]; } set x(v) { this.value[0] = v; } get y() { return this.value[1]; } set y(v) { this.value[1] = v; } } const t2 = [ new Vec2(10, 10), new Vec2(100, 10), new Vec2(100, 100), new Vec2(10, 100), ]; const c = document.getElementById("myCanvas"); const ctx = c.getContext("2d"); ctx.beginPath(); t2.forEach(point => ctx.lineTo(...point.get())); ctx.closePath(); ctx.stroke(); 
 <canvas id="myCanvas"></canvas> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM