我为OpenHeatMap开源项目维护并行Flash和HTML5 / Canvas渲染器。我被两个版本之间的小数坐标的填充多边形的渲染不一致所困扰。如果渲染两个共享边缘的多边形,Canvas将沿着该边缘显示可见的连接,而Flash将无缝地将两者融合在一起,如果它们是相同的颜色则没有可见的差异。我在这里整理了一个最小页面以显示问题:
http://web.mailana.com/labs/stitchingbug/
[Gak,垃圾邮件预防阻止了这一点,但是请看这里的截图web.mailana.com/labs/stitchingbug.png]
源代码以及执行相同操作的Flash项目位于:
github.com/petewarden/stitchingbug
根本问题在于,如果不能在没有接缝的情况下将多边形缝合在一起,则无法进行任何复杂的多边形渲染。我不确切知道Flash的填充规则是什么,但是它们产生了正确的结果,就像3D渲染器一样。有没有人有客户端修复来解决这个问题?它是跨浏览器,这使它看起来很刻意,因此任何对所用规则的引用也将受到赞赏。这是Canvas代码:
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgb(0,0,0)';
ctx.beginPath()
ctx.moveTo(0, 0);
ctx.lineTo(50.5, 0);
ctx.lineTo(50.5, 100);
ctx.lineTo(0, 100);
ctx.closePath();
ctx.fill();
ctx.beginPath()
ctx.moveTo(50.5, 0);
ctx.lineTo(100, 0);
ctx.lineTo(100, 100);
ctx.lineTo(50.5, 100);
ctx.closePath();
ctx.fill();
答案 0 :(得分:3)
这是一个老问题,但我遇到了同样的问题。
我发现在两个多边形之间画一条线(或者它们周围的轮廓)解决了这个问题(至少在firefox和chrome中)。
这似乎至少填补了chrome和firefox的空白。在ctx.stroke()
之后调用ctx.fill()
就足够了,或者按如下方式绘制一行:
ctx.beginPath()
ctx.moveTo(50.5, 0);
ctx.lineTo(50.5, 100);
ctx.stroke();
并确保当然设置strokeStyle。
答案 1 :(得分:1)
您是否考虑截断所有绘图线?它不应该降低质量,它可能会解决您的问题。
你还可以在令人不安的区域画一条线,使问题不可见。
如果一切都失败了,那应该有用。
答案 2 :(得分:1)
即使坐标都是整数,我也可以在Chrome 41.0.2272.89 m中看到同样的问题:http://jsfiddle.net/xgd03fyb/
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.lineWidth = 0;
context.fillStyle = 'black';
context.beginPath();
context.moveTo(100, 100);
context.lineTo(200, 200);
context.lineTo(200, 100);
context.closePath();
context.fill();
context.beginPath();
context.moveTo(100, 100);
context.lineTo(100, 200);
context.lineTo(200, 200);
context.closePath();
context.fill();
我怀疑这个问题可能是顺时针/逆时针不匹配造成的,因为在过去我曾经使用过的某些库会影响哪些边缘被绘制为实体,哪些边缘是透明的,哪些是抗锯齿的。 但是,更改第二个三角形中lineTo()调用的顺序似乎没有任何效果。
我还尝试从"evenodd"
来自默认"nonzero"
的fillStyle(传递给fill()的参数),但没有运气。
从规范https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-fill我不清楚这应该如何运作所以我已经提交了错误以了解详情:https://www.w3.org/Bugs/Public/show_bug.cgi?id=28217