Javascript 如何在画布元素中正确绘制带间隙的圆?
我想画一个圆圈。但是,不是真的。我想要一系列的弧(段),这将意味着一个完整的圆。它会旋转,会很棒。但我显然做错了什么。 我不想要从中心到圆弧起点的直线(第一条没有)。 我一直在用画布学习基本的绘画,希望有一天能理解正在发生的事情,甚至更多,但我迫不及待地想知道在这种情况下到底出了什么问题。Javascript 如何在画布元素中正确绘制带间隙的圆?,javascript,html,canvas,html5-canvas,drawing,Javascript,Html,Canvas,Html5 Canvas,Drawing,我想画一个圆圈。但是,不是真的。我想要一系列的弧(段),这将意味着一个完整的圆。它会旋转,会很棒。但我显然做错了什么。 我不想要从中心到圆弧起点的直线(第一条没有)。 我一直在用画布学习基本的绘画,希望有一天能理解正在发生的事情,甚至更多,但我迫不及待地想知道在这种情况下到底出了什么问题。 非常感谢您的帮助。避免复杂数学的最简单方法是调用.beginPath()和.stroke()用于每个段。我知道这是非常重复的,但它看起来是这样的: function draw() { var can
非常感谢您的帮助。避免复杂数学的最简单方法是调用
.beginPath()
和.stroke()代码>用于每个段。我知道这是非常重复的,但它看起来是这样的:
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.lineWidth = 15;
ctx.strokeStyle = 'hsla(111, 56%, 50%, 0.67)';
ctx.beginPath();
ctx.arc(250, 250, 100, 0, Math.PI * 8 / 30);
ctx.stroke();
ctx.beginPath();
ctx.arc(250, 250, 100, Math.PI * 12 / 30, Math.PI * 20 / 30);
ctx.stroke();
ctx.beginPath();
ctx.arc(250, 250, 100, Math.PI * 24 / 30, Math.PI * 32 / 30);
ctx.stroke();
ctx.beginPath();
ctx.arc(250, 250, 100, Math.PI * 36 / 30, Math.PI * 44 / 30);
ctx.stroke();
ctx.beginPath();
ctx.arc(250, 250, 100, Math.PI * 48 / 30, Math.PI * 56 / 30);
ctx.stroke();
}
}
draw();
这是你的小提琴:避免复杂数学的最简单方法是调用.beginPath()
和.stroke()代码>用于每个段。我知道这是非常重复的,但它看起来是这样的:
function draw() {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.lineWidth = 15;
ctx.strokeStyle = 'hsla(111, 56%, 50%, 0.67)';
ctx.beginPath();
ctx.arc(250, 250, 100, 0, Math.PI * 8 / 30);
ctx.stroke();
ctx.beginPath();
ctx.arc(250, 250, 100, Math.PI * 12 / 30, Math.PI * 20 / 30);
ctx.stroke();
ctx.beginPath();
ctx.arc(250, 250, 100, Math.PI * 24 / 30, Math.PI * 32 / 30);
ctx.stroke();
ctx.beginPath();
ctx.arc(250, 250, 100, Math.PI * 36 / 30, Math.PI * 44 / 30);
ctx.stroke();
ctx.beginPath();
ctx.arc(250, 250, 100, Math.PI * 48 / 30, Math.PI * 56 / 30);
ctx.stroke();
}
}
draw();
这是你的小提琴:移动到弧线的起点,而不是中心。这一点最容易通过平移到圆的中心来实现,如下所示
moveTo必须位于弧的起点,而不是弧的中心。这一点最容易通过平移到圆的中心来实现,如下所示
如果您想要一个灵活的解决方案,例如,如果您想要更改段的数量、每个段的大小,那么您可以创建一个通用函数,如下所示:
/**
* ctx = context
* x / y = center
* radius = of circle
* offset = rotation in angle (radians)
* segments = How many segments circle should be in
* size = size of each segment (of one segment) [0.0, 1.0]
*/
function dashedCircle(ctx, x, y, radius, offset, segments, size) {
var pi2 = 2 * Math.PI, /// cache 2*Math.PI = 360 degrees in rads
segs = pi2 / segments, /// calc. size of each segment in rads
len = segs * size, /// calc. length of segment in rads
i = 0,
ax, ay;
ctx.save();
ctx.translate(x, y);
ctx.rotate(offset); /// rotate canvas
ctx.translate(-x, -y);
for(; i < pi2; i += segs) {
ax = x + radius * Math.cos(i); /// calculate start position of arc
ay = y + radius * Math.sin(i);
ctx.moveTo(ax, ay); /// make sure to move to beginning of arc
ctx.arc(x, y, radius, i, i + len); /// draw arc
}
ctx.restore(); /// remove rotation
}
使用“偏移”参数可以轻松地对其进行旋转:
var offset = 0;
var step = 0.03;
var pi2 = 2 * Math.PI;
(function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
dashedCircle(ctx, 250, 250, 100, offset % pi2, 5, 0.7);
ctx.stroke();
offset += step;
requestAnimationFrame(loop);
})();
如果您想要一个灵活的解决方案,例如,如果您想要更改段的数量、每个段的大小,那么您可以创建一个通用函数,例如:
/**
* ctx = context
* x / y = center
* radius = of circle
* offset = rotation in angle (radians)
* segments = How many segments circle should be in
* size = size of each segment (of one segment) [0.0, 1.0]
*/
function dashedCircle(ctx, x, y, radius, offset, segments, size) {
var pi2 = 2 * Math.PI, /// cache 2*Math.PI = 360 degrees in rads
segs = pi2 / segments, /// calc. size of each segment in rads
len = segs * size, /// calc. length of segment in rads
i = 0,
ax, ay;
ctx.save();
ctx.translate(x, y);
ctx.rotate(offset); /// rotate canvas
ctx.translate(-x, -y);
for(; i < pi2; i += segs) {
ax = x + radius * Math.cos(i); /// calculate start position of arc
ay = y + radius * Math.sin(i);
ctx.moveTo(ax, ay); /// make sure to move to beginning of arc
ctx.arc(x, y, radius, i, i + len); /// draw arc
}
ctx.restore(); /// remove rotation
}
使用“偏移”参数可以轻松地对其进行旋转:
var offset = 0;
var step = 0.03;
var pi2 = 2 * Math.PI;
(function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
dashedCircle(ctx, 250, 250, 100, offset % pi2, 5, 0.7);
ctx.stroke();
offset += step;
requestAnimationFrame(loop);
})();
+1回答得好。注意:由于在draw()中进行翻译,因此可能需要使用ctx.save/ctx.restore进行包装。否则,对draw()的任何进一步调用都将累积转换,并将绘图从画布中移出。提问者需要补充的一点是:既然你已经转换到中心点了,你最好添加ctx.rotate(弧度角),这将使你的圆弧也可以旋转。太棒了!正如小提琴所示,它很有效,它帮助我更新了余弦、正弦和单位圆的知识。这对现在很有帮助,从长远来看也很有用。所以,非常感谢!我需要的正是对我应该“搬到哪里”以及如何计算的理解。我想我基本上是在几何上迷路了=P现在,我们可以在这里看到“最终”产品的辉煌+回答得好。注意:由于在draw()中进行翻译,因此可能需要使用ctx.save/ctx.restore进行包装。否则,对draw()的任何进一步调用都将累积转换,并将绘图从画布中移出。提问者需要补充的一点是:既然你已经转换到中心点了,你最好添加ctx.rotate(弧度角),这将使你的圆弧也可以旋转。太棒了!正如小提琴所示,它很有效,它帮助我更新了余弦、正弦和单位圆的知识。这对现在很有帮助,从长远来看也很有用。所以,非常感谢!我需要的正是对我应该“搬到哪里”以及如何计算的理解。我想我基本上是在几何上迷路了=P现在,我们可以在这里看到“最终”产品的辉煌起初,我试过这样的方法。这确实有效,但我觉得我错过了一些重要的东西。最后,我意识到复杂的数学并没有那么复杂,而且实际上非常有趣=D一种我将来会反复使用的知识。还有别的东西。我开始明白这里不需要closePath
。它不是endPath
。它不像我想象的那样。这是一个宝贵的教训。您可以在这把小提琴中亲自看到:.closePath()将端点与起点连接起来,圆弧不需要它。此外,在stroke()之后调用它也没有意义,因为stroke是光栅化路径(轮廓)的方法。@jaywalking101酷!很高兴我也能从中学到一些东西。我更新了我的答案。起初,我试过这样的方法。这确实有效,但我觉得我错过了一些重要的东西。最后,我意识到复杂的数学并没有那么复杂,而且实际上非常有趣=D一种我将来会反复使用的知识。还有别的东西。我开始明白这里不需要closePath
。它不是endPath
。它不像我想象的那样。这是一个宝贵的教训。您可以在这把小提琴中亲自看到:.closePath()将端点与起点连接起来,圆弧不需要它。此外,在stroke()之后调用它也没有意义,因为stroke是光栅化路径(轮廓)的方法。@jaywalking101酷!很高兴我也能从中学到一些东西。我更新了我的答案。哇!令人惊叹的我在研究你的小提琴,尽可能地理解它们。我已经学到了很多!起初,尺寸一点也不清楚。现在我看到它就像一个相对大小。应实际绘制多少弧。考虑到每个圆弧都是整圆的一部分。这真的很聪明,这是我想要内化的洞察力。现在我的需求非常具体,但是,我从你的代码中学到的东西是无价的。多谢各位=我现在的目标已经完成了!:哇!令人惊叹的我在研究你的小提琴,尽可能地理解它们。我已经学到了很多!起初,尺寸一点也不清楚。现在我看到它就像一个相对大小。应实际绘制多少弧。考虑到每个圆弧都是整圆的一部分。这真的很聪明,这是一种我想要内化的洞察力。现在我的需求非常具体,但仍然是我想要的