Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在画布元素中正确绘制带间隙的圆?_Javascript_Html_Canvas_Html5 Canvas_Drawing - Fatal编程技术网

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酷!很高兴我也能从中学到一些东西。我更新了我的答案。哇!令人惊叹的我在研究你的小提琴,尽可能地理解它们。我已经学到了很多!起初,尺寸一点也不清楚。现在我看到它就像一个相对大小。应实际绘制多少弧。考虑到每个圆弧都是整圆的一部分。这真的很聪明,这是我想要内化的洞察力。现在我的需求非常具体,但是,我从你的代码中学到的东西是无价的。多谢各位=我现在的目标已经完成了!:哇!令人惊叹的我在研究你的小提琴,尽可能地理解它们。我已经学到了很多!起初,尺寸一点也不清楚。现在我看到它就像一个相对大小。应实际绘制多少弧。考虑到每个圆弧都是整圆的一部分。这真的很聪明,这是一种我想要内化的洞察力。现在我的需求非常具体,但仍然是我想要的