在画布上绘制花式圆圈具有奇怪的效果

时间:2013-01-16 09:39:01

标签: javascript geometry html5-canvas drawing

我正在尝试在画布上绘制一个圆圈,它的生成如下:

Circle with weird effect,并缩放:enter image description here

我不知道为什么会发生这种情况,虽然我之前已经看过这种效果,但我怀疑它与部分像素有关(虽然我不是这样做的)。可以在此jsfiddle看到一个工作示例。

总结代码,我正在使用一个函数绘制圆圈。我逐渐向内绘制内外边缘,随时调整alpha。代码如下所示:

function drawCircle(x, y, radius, startAngle, endAngle, antiClockwise, lineWidth, r, g, b, a) {
    c.beginPath(); 

    var w = Math.abs(lineWidth / 2);

    var alphaFactor = a / w;
    var alpha = alphaFactor;

    var outer = radius + w;
    var inner = radius - w;

    // draw centre line
    c.lineWidth = 1;
    c.strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
    c.arc(x, y, radius, startAngle, endAngle, true); 
    c.stroke();

    for(i = 0; i < w; i++, inner++, outer--, alpha += alphaFactor) {
        // draw inner
        c.beginPath(); 
        c.strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')';
        c.arc(x, y, inner, startAngle, endAngle, true); 
        c.stroke();

        // draw outer
        c.beginPath(); 
        c.arc(x, y, outer, startAngle, endAngle, true); 
        c.stroke();
    }
};

我相信我可以使用径向渐变来解决这个问题(我认为它会更快,取决于线的宽度),但是我想理解为什么会出现上面显示的影响。

2 个答案:

答案 0 :(得分:1)

我想这是由于非直线的抗锯齿/圆角效应(圆圈包含很多)。特别是,具有(非常)小的线宽。我的猜测是,这导致部分重叠的圆形线条,彼此部分相邻的线条,甚至可能在某些地方留下间隙的线条......

问题似乎是通过增加线宽来解决的:

c.lineWidth = 1.4;

请参阅更新后的jsFiddle demo

答案 1 :(得分:0)

我通过不绘制单独的线并仅使用径向渐变绘制一条线来重新设置我正在寻找的效果来解决问题:

enter image description here

这看起来(afaict)效率更高,因为它只使用一次填充,而不是多次冲击。

可以在此JSFiddle看到解决方案,而代码非常小:

$(function () {
  draw(document.getElementById('canvas').getContext('2d'));

  function draw(ctx) {
    var radgrad = ctx.createRadialGradient(60, 60, 0, 60, 60, 60);
    radgrad.addColorStop(0.8, 'rgba(255,0,0,0)');
    radgrad.addColorStop(0.85, 'rgba(255,0,0,.6)');
    radgrad.addColorStop(0.9, 'rgba(255,0,0,1)');
    radgrad.addColorStop(0.95, 'rgba(255,0,0,.6)');
    radgrad.addColorStop(1, 'rgba(255,0,0,0)');

    ctx.fillStyle = radgrad;
    ctx.arc(60, 60, 60, 0, 2 * Math.PI, true);
    ctx.fill();
  }
});

我将我的解决方案从解决方案派生到另一个question