非常大的HTML5画布圈不精确

时间:2012-01-03 15:53:54

标签: graphics drawing html5-canvas

我正在开发一个用户在HTML5画布上绘制欧几里德结构的应用程序。因此,我无法真正限制某些形状的大小。当我在屏幕上画出非常大的圆圈时,我注意到非常大的圆圈没有恒定的半径。

更具体地说,由两个点定义的圆,一个中心点和一个指定半径的圆不再通过半径点!

Large circle with radius point

进步大圈子。这些都应该通过E点。

Larger circles

在45度= PI / 4的倍数处不会出现错误。在这些倍数之间,误差最大(例如PI / 8)

这是一个包含上面第一个例子的jsfiddle:

http://jsfiddle.net/D28J2/2/

我的问题:为什么会发生这种情况?有没有办法(有效地)解决这个问题?

4 个答案:

答案 0 :(得分:3)

我完全解决这个问题的方法是使用贝塞尔曲线滚动我自己实现的圆绘制近似。可以在此处找到详细说明实施的文章http://www.tinaja.com/glib/ellipse4.pdf

function magic_circle(ctx, x, y, r){
  m = 0.551784

  ctx.save()
  ctx.translate(x, y)
  ctx.scale(r, r)

  ctx.beginPath()
  ctx.moveTo(1, 0)
  ctx.bezierCurveTo(1,  -m,  m, -1,  0, -1)
  ctx.bezierCurveTo(-m, -1, -1, -m, -1,  0)
  ctx.bezierCurveTo(-1,  m, -m,  1,  0,  1)
  ctx.bezierCurveTo( m,  1,  1,  m,  1,  0)
  ctx.closePath()
  ctx.restore()
}

只有这四个部分,我能够比使用Google Chrome画布实现的内容更接近圆圈。

答案 1 :(得分:2)

这可能是浮点截止误差。可能因为正弦和余弦不能给出完全准确的值。您可以通过旋转画布而不是弧来绕过它(至少在Chrome中)。

ctx.save();          // Save the canvas so we can rotate back.
ctx.translate(x, y); // Translate to the origin point.
ctx.rotate(alpha);   // Rotate the proper angle.

ctx.arc(0, 0, 3, 0, Math.PI*2); // Draw the small circle at the origin.
ctx.fill();

ctx.arc(r, 0, r, 0, Math.PI*2); // Create a big with the origin 1 radius away.
ctx.restore();                  // Restore the canvas to the original orientation
                                // before drawing.  Otherwise the circle looks bad.
ctx.strokeStyle = "black";
ctx.stroke();                   // Draw!

我是操纵画布而不是形状的忠实粉丝。它为您提供了更合理的工作区域。见http://jsfiddle.net/D28J2/10/

答案 2 :(得分:1)

只是把它扔到那里,但如果没有指定足够数量的PI,这可能是一个问题吗?每当我做这样的事情时,我往往会略微过火,并使用大约10位数的PI。

答案 3 :(得分:0)

在谷歌浏览器中我可以重复这个问题,但在IE 9和IE 10中一切都很好。

所以我的猜测是Chrome中的实现是错误的。它可能是一个舍入误差,或者他们使用插值方法来避免不太精确的sin和cos。

在这里查看:HTML5 canvas arcs not rendering correctly in Google Chrome

我能想象的唯一工作就是用你自己的代码或使用(jQuery?)插件来绘制圆圈,为你做这件事。