javascript 在 HTML5 Canvas 上绘制多个圆圈的问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23668459/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Issue on Drawing Multiple Circles on HTML5 Canvas
提问by Suffii
Can you please take a look at thisdemo and let me know how I can draw multiple circles in a canvas with different coordinate without repeating bunch of codes?
你能看看这个演示,让我知道如何在不同坐标的画布上绘制多个圆圈而不重复一堆代码吗?
As you can see on Demo and following code
正如您在 Demo 和以下代码中所见
var ctx = $('#canvas')[0].getContext("2d");
ctx.fillStyle = "#00A308";
ctx.beginPath();
ctx.arc(150, 50, 5, 0, Math.PI * 2, true);
ctx.arc(20, 85, 5, 0, Math.PI * 2, true);
ctx.arc(160, 95, 5, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
I tried to have them under ctx
but it is not correct so I tried to use for loop to create 50 points but I have issue on repeating and adding code like ctx.fill(); for all of them.
Can you please let me know how I can fix this?
我试图将它们放在下面,ctx
但它不正确,所以我尝试使用 for 循环来创建 50 个点,但是我在重复和添加诸如 ctx.fill() 之类的代码时遇到问题;对于他们所有人。你能告诉我如何解决这个问题吗?
Thanks
谢谢
采纳答案by Spencer Wieczorek
This is because you are not closing the path, either using fill()
or closePath()
will close the path so it does not try and connect all the items. fill()
fills in the circles and closes the path so we can just use that. Also you need to use beginPath()
, so that they are separate from each other. Here is your three circles:
这是因为您没有关闭路径,无论是使用fill()
还是closePath()
将关闭路径,因此它不会尝试连接所有项目。fill()
填充圆圈并关闭路径,这样我们就可以使用它了。您还需要使用beginPath()
,以便它们彼此分开。这是你的三个圈子:
var coords = [ [150,50], [20,85], [160,95] ];
for(var i = 0; i < coords.length; i++){
ctx.beginPath();
ctx.arc(coords[i][0], coords[i][1], 5, 0, Math.PI * 2, true);
ctx.fill();
}
To not repeat a bunch of code and have unique coordinates store your X
and Y
position in an array and use a for
loop to go through it.
为了不重复一堆代码并拥有唯一的坐标,将您的X
和Y
位置存储在一个数组中并使用for
循环来遍历它。
Update:
更新:
A more efficient way to do which achieves the same effect this would be to only use a single path and use moveTo()
instead of creating a new path when drawing each circle:
实现相同效果的更有效方法是仅使用单个路径并moveTo()
在绘制每个圆时使用而不是创建新路径:
ctx.beginPath();
for(var i = 0; i < coords.length; i++){
ctx.moveTo(coords[i][0], coords[i][1]);
ctx.arc(coords[i][0], coords[i][1], 5, 0, Math.PI * 2, true);
}
ctx.fill();
回答by Adria
Constantly creating and closing new paths is not good advice.
不断创建和关闭新路径并不是一个好建议。
You should batch together all fills / strokes of the same style, and execute them in a single draw call. The performance difference between these approaches becomes apparent very quickly with increasing polygon count.
您应该将相同样式的所有填充/笔触批处理在一起,并在单个绘制调用中执行它们。随着多边形数量的增加,这些方法之间的性能差异很快就会变得明显。
The way to go about it is to move the pen and make the path construction call for each circle; stroke/fill in the end in one shot. However, there's a quirk involved here. When you have the point moved to the center and draw the circle, you'd still see a horizontal radius line, drawn from the center of the circle, to the circumference.
实现它的方法是移动笔并为每个圆调用路径构建;一击完成/填充。然而,这里有一个怪癖。当您将点移动到中心并绘制圆时,您仍然会看到从圆的中心到圆周绘制的水平半径线。
To avoid this artefact, instead of moving to the center, we move to the circumference. This skips the radius drawing. Essentially all these commands are for tracing a path and there's no way to describe a discontinuity without calling closePath
; usually moveTo
does it but HTML5 canvas API it doesn't. This is a simple workaround to counter that.
为了避免这种伪影,我们不是移动到中心,而是移动到圆周。这将跳过半径绘制。基本上所有这些命令都是用于跟踪路径,如果不调用就无法描述不连续性closePath
;通常moveTo
会这样做,但 HTML5 canvas API 不会。这是一个简单的解决方法来解决这个问题。
const pi2 = Math.PI * 2;
const radius = 5;
ctx.fillStyle = '#00a308';
ctx.beginPath();
for( let i=0, l=coords.length; i < l; i++ )
{
const p = coords[i],
x = p.x,
y = p.y;
ctx.moveTo( x + radius, y ); // This was the line you were looking for
ctx.arc( x, y, radius, 0, pi2 );
}
// Finally, draw outside loop
ctx.stroke();
ctx.fill();
Also worth considering, is using transformations, and drawing everything relative to a local frame of reference.
同样值得考虑的是,使用转换,并绘制相对于本地参考系的所有内容。
ctx.fillStyle = '#00a308';
ctx.beginPath();
for( let i=0, l=coords.length; i < l; i++ )
{
const p = coords[i];
ctx.save();
ctx.translate( p.x + radius, p.y );
ctx.moveTo( 0, 0 );
ctx.arc( 0, 0, radius, 0, pi2 );
ctx.restore();
}
ctx.stroke();
ctx.fill();
回答by Bonnie Milian
ctx.beginPath();
points.forEach(point => {
ctx.moveTo( point.x, point.y );
ctx.arc(point.x,point.y,1,0,Math.PI*2,false);
});
ctx.fill();
回答by light
Example Fiddleof lots of circles in different locations drawn in a loop.
示例在循环中绘制在不同位置的许多圆圈。
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext( '2d' );
var cx = canvas.width/2;
var cy = canvas.height/2;
ctx.fillStyle = "#00A308";
var total_circles = 50;
var radius = 100;
for(i = 0; i < total_circles; i++){
var angle = i * 2 * Math.PI/total_circles;
var x = cx + Math.cos(angle) * radius;
var y = cy + Math.sin(angle) * radius;
ctx.beginPath();
ctx.arc(x, y, 2, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
}
回答by Zack Argyle
You can easily create several circles with a for loop. You really just need to draw an arc and fill it each time. Using your example, you could do something like this.
您可以使用 for 循环轻松创建多个圆圈。你真的只需要画一个弧线并每次都填充它。使用你的例子,你可以做这样的事情。
var ctx = $('#canvas')[0].getContext("2d");
ctx.fillStyle = "#00A308";
for (var i = 0; i < 3; i++) {
ctx.arc(50 * (i+1), 50 + 15 * i, 5, 0, Math.PI * 2, true);
ctx.fill();
}