[英]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();
該代碼正在做一些奇怪的事情。
它在循環內稱為stroke
。 這意味着它將繪制第一條線,然后繪制第一條和第二條線,然后繪制第一條,第二條和第三條線,依此類推...
如果要分別繪制每條線,則需要在每次調用stroke
之后調用beginPath
。 如果只想繪制所有線條,則應該在末尾僅調用一次描邊。
每個段都使用moveTo / lineTo。 這不是制作多邊形,而是繪制N條線段。 不同之處在於,如果您調用fill
而不是stroke,則它將失敗,因為代碼沒有制作多邊形,而是制作了單獨的線條。
您不需要第一個moveTo
。 調用beginPath
之后,對lineTo
的首次調用將自動為moveTo
(感謝@Kaiido)
它沒有將最后一點與第一點聯系起來。
您可以使用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.