我使用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绘制的圆之间的区别
答案 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();
(是的,lineCap是红鲱鱼。)