在Chrome中,放大时Canvas Arcs会扭曲

时间:2015-06-18 01:10:19

标签: google-chrome canvas html5-canvas

画布context.arc()方法在放大上下文时绘制扭曲的弧。看起来弧线(差)用贝塞尔曲线近似。在Firefox中正常工作。 IE中未经测试。

前段时间我发现了这个问题,但最近似乎变得更糟(我不知道什么时候)。

我在StackOverflow上发现了一些画布问题,但不是这个问题。如果您知道它是已报告问题的表现形式,请转发链接。我已经通过Chrome的帮助/报告问题机制进行了报告。

在我自己编写之前,有没有人有解决方法? ......也许是一种过载或替代的'弧'方法?

可在此处查看以下演示:http://keveney.com/chrome_arc_bug.html

paint_canvas();

// simulate circle with line segments
//
function regular_polygon(ctx, segments, cx, cy, r) {
  var i, a;

  ctx.moveTo(cx + r, cy);

  for (i = 0; i < segments; i++) {
    a = (Math.PI * 2) * i / segments;
    ctx.lineTo(cx + r * Math.cos(a), cy + r * Math.sin(a));
  }

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

function paint_canvas() {
  var ctx;

  // draw unscaled circle using canvas 'arc' method
  //
  ctx = document.getElementById('canv').getContext('2d');

  ctx.beginPath();
  ctx.strokeStyle = "#000";
  ctx.lineWidth = 1.25;
  ctx.arc(250, 250, 200, 0, 2 * Math.PI, false);
  ctx.stroke();

  // draw enclosing polygons
  //
  ctx.beginPath();
  ctx.strokeStyle = "#c00";
  regular_polygon(ctx, 36, 250, 250, 215);
  regular_polygon(ctx, 36, 250, 250, 185);

  // the same but scaled up from smaller units
  //
  ctx = document.getElementById('canv2').getContext('2d');

  ctx.beginPath();
  ctx.strokeStyle = "#000";
  ctx.scale(100, 100);
  ctx.lineWidth = 1.25 / 100;
  ctx.arc(2.5, 2.5, 2, 0, 2 * Math.PI, false);
  ctx.stroke();

  ctx.beginPath();
  ctx.strokeStyle = "#c00";
  regular_polygon(ctx, 36, 2.5, 2.5, 2.15);
  regular_polygon(ctx, 36, 2.5, 2.5, 1.85);
}
body {
  background-color: #F4F4F4;
  width: 800px;
  margin-left: auto;
  margin-right: auto;
}
canvas {
  background-color: #FFFFFF;
}
<p>Chrome arc scaling bug</p>
<canvas id="canv" height=500 width=500></canvas>
<canvas id="canv2" height=500 width=500></canvas>

<p>expected: Both images should be identical.</p>
<p>actual: Arc in second image is badly distorted.</p>
<p>Issue reported 6/17/2015.</p>
<p>tested with 43.0.2357.124 (64-bit)</p>
<p>This issue was observed some time ago, but has gotten worse in recent releases of Chrome. Not tested on Internet Explorer. If you find a convenient solution,
  please notify Matt Keveney, matt@keveney.com</p>

2 个答案:

答案 0 :(得分:1)

这种效果源于近似半径较小的圆形,看起来更像是一个正方形而不是一个圆形。

enter image description here

如果你故意制作这种圆圈,我建议制作一个绘制半径圆的函数,该圆将产生一个很好的近似圆形,可以很好地缩放(在我的例子中我选择了半径为10)在下面),然后调整参数以达到想要的圆圈。

function drawSmallArc(x,y,r,scale) {
    var adjust = 10/r;
    ctx.save();
    ctx.beginPath();
    ctx.strokeStyle = "#00f";
    ctx.scale(scale/adjust, scale/adjust);
    ctx.lineWidth = 1.25 / scale * adjust;
    ctx.arc(x*adjust, y*adjust,r*adjust,0,2 * Math.PI, false);
    ctx.stroke();
    ctx.restore();
}

以下行动

var c = document.getElementById("canvas");
var ctx = c.getContext("2d");

//Two referense circles.
ctx.beginPath();
ctx.strokeStyle = "#0f0"; //green
ctx.lineWidth = 1.25;
ctx.arc(250, 250, 180, 0, 2 * Math.PI, false);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle = "#0f0"; //green
ctx.lineWidth = 1.25;
ctx.arc(250, 250, 220, 0, 2 * Math.PI, false);
ctx.stroke();

//Red circle using OP's original circle
ctx.save();
ctx.beginPath();
ctx.strokeStyle = "#f00"; //Red
ctx.lineWidth = 1.25 / 100;
ctx.scale(100,100);
ctx.arc(2.5, 2.5, 2, 0, 2 * Math.PI, false);
ctx.stroke();
ctx.restore();

//blue circle with better approximation of circle.
drawSmallArc(2.5,2.5,2,100);

function drawSmallArc(x,y,r,scale) {
    var adjust = 10/r;
    ctx.save();
    ctx.beginPath();
    ctx.strokeStyle = "#00f";
    ctx.scale(scale/adjust, scale/adjust);
    ctx.lineWidth = 1.25 / scale * adjust;
    ctx.arc(x*adjust, y*adjust,r*adjust,0,2 * Math.PI, false);
    ctx.stroke();
    ctx.restore();
}
<canvas id="canvas" height=500 width=500></canvas>

答案 1 :(得分:0)

我现在使用高计数多边形解决了这个问题。我不是完全兼容的直接替代电弧,所以这里不再重复。它与上面示例代码中用于渲染红色参考多边形的函数非常相似。

我仍然对更好的解决方案或解决问题的Chrome更新感兴趣,以防有人发现。