如何在画布上画圆圈?

时间:2015-07-14 08:02:38

标签: javascript html5 canvas

我使用javascript和画布绘制数学设计的比例(测量扭矩,包括牛顿米和英尺 - 磅)。我一直使用三角法定位我的刻度线,并自然地使用arc绘制弧线。他们需要排队时出现问题,但有一些奇怪的失真。然后我绘制了一个非常大的圆圈并将其与GIMP中的圆形选择进行比较,并且存在失真。圆圈周围每45度一致,但在这些节点之间,画布绘制的圆圈向外偏离,就像八角形可以向外圆得太远而近似圆形。

为什么会出现这些扭曲?如何在画布上绘制一个真正的圆形圆圈?

这是我用来生成扭曲圆圈的代码。

<!DOCTYPE html>
<html>
  <body>
    <canvas width=8000 height=8000 id='myCanvas'></canvas>
    <script>
      var canvas = document.getElementById('myCanvas');
      var context = canvas.getContext('2d');
      context.beginPath();
      context.arc(4000, 4000, 3200, 0, Math.PI*2, false);
      context.lineWidth = 1;
      context.strokeStyle = '#ff0000';
      context.lineCap = 'square';
      context.stroke();
    </script>
  </body>
</html>

这可能不是最小的,我不知道context.lineCap的相关性,但它是基于此代码的遗迹。 以下屏幕截图显示了GIMP绘制的圆与Chrome绘制的圆之间的区别 screenshot

1 个答案:

答案 0 :(得分:10)

这是Chromium Bug #164241(声明已修复,但修复程序可能尚未解决)。简短的回答是:Chrome是approximating circles with composite Bezier curves

我无法在Chromium(43.0.2357.130,Ubuntu)上自行复制,但它确实在Firefox 39上发生,尽管我无法找到类似的Firefox错误报告。事实上它每90度都是正确的(不是45度,至少不是我的),这表明圆圈正在被4条曲线近似,因为曲线端点保证是正确的。

幸运的是,有一个简单的解决方法:创建一条包含4条以上曲线的路径。对于您正在使用的半径,8或甚至6应该足够,但如果您想要安全使用,则可以使用更多。或者你可以增加曲线的数量作为半径的函数,尽管计算最佳函数(为给定半径r产生精确圆的最小n)是非平凡的。

context.beginPath();
var n=8; // 4 is the default behaviour. higher is better, also slower
for (var i=0; i<n; i++) {
    context.arc(4000, 4000, 3200, Math.PI*2*i/n, Math.PI*2*(i+1)/n, false);
}
context.stroke();

另见this question

(是的,lineCap是红鲱鱼。)