如何在canvas元素中正确绘制带有间隙的圆?

时间:2014-02-10 13:51:24

标签: javascript html5 canvas html5-canvas drawing

我想画一个圆圈。但是,不是真的。我想要一系列弧线(线段),这意味着一个完整的圆圈。它会旋转,它会很棒。但我显然做错了什么。 Please, check this fiddle: http://jsfiddle.net/utWdM/

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.moveTo(250, 250);
        ctx.arc(250, 250, 100, Math.PI * 12 / 30, Math.PI * 20 / 30);
        ctx.moveTo(250, 250);
        ctx.arc(250, 250, 100, Math.PI * 24 / 30, Math.PI * 32 / 30);
        ctx.moveTo(250, 250);
        ctx.arc(250, 250, 100, Math.PI * 36 / 30, Math.PI * 44 / 30);
        ctx.moveTo(250, 250);
        ctx.arc(250, 250, 100, Math.PI * 48 / 30, Math.PI * 56 / 30);

        ctx.stroke();
        ctx.closePath();
    }
}

draw();

我不希望从中心到弧线的起点(第一个没有它)。 我一直在用帆布学习基本绘图,并希望有一天能够了解正在发生的事情,但是我迫不及待想知道在这种情况下出了什么问题。 任何帮助,高度赞赏。

3 个答案:

答案 0 :(得分:3)

如果你想要一个灵活的解决方案,即。如果你想改变段的数量,每个段的大小,那么你可以创建一个通用的函数,如:

/**
 * 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
}

然后在您的代码中,您只需致电:

ctx.beginPath();

dashedCircle(ctx, 250, 250, 100, 0, 5, 0.7);

ctx.lineWidth = 15;
ctx.strokeStyle = 'hsla(111, 56%, 50%, 0.67)';
ctx.stroke();
/// don't closePath here

<强> Modified fiddle here

使用offset参数可以轻松旋转它:

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);
})();

<强> Rotating circle fiddle

答案 1 :(得分:1)

避免复杂数学运算的最简单方法是为每个段调用.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();

这是你的小提琴:http://jsfiddle.net/utWdM/13/

答案 2 :(得分:1)

moveTo需要到弧的开头而不是中心。这最容易通过转换到圆的中心来实现,如下所示。 http://jsfiddle.net/utWdM/1

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.translate(250,250);
        ctx.arc(0, 0, 100, 0, Math.PI * 8 / 30);
        ctx.moveTo(100*Math.cos(Math.PI*12/30), 100*Math.sin(Math.PI*12/30));
        ctx.arc(0, 0, 100, Math.PI * 12 / 30, Math.PI * 20 / 30);
        ctx.moveTo(100*Math.cos(Math.PI*24/30), 100*Math.sin(Math.PI*24/30));
        ctx.arc(0, 0, 100, Math.PI * 24 / 30, Math.PI * 32 / 30);
        ctx.moveTo(100*Math.cos(Math.PI*36/30), 100*Math.sin(Math.PI*36/30));
        ctx.arc(0, 0, 100, Math.PI * 36 / 30, Math.PI * 44 / 30);
        ctx.moveTo(100*Math.cos(Math.PI*48/30), 100*Math.sin(Math.PI*48/30));
        ctx.arc(0, 0, 100, Math.PI * 48 / 30, Math.PI * 56 / 30);

        ctx.stroke();
        ctx.closePath();
    }
}