How can I avoid polygon edge stitching artifacts in HTML5 Canvas?

后端 未结 3 681
无人及你
无人及你 2021-01-02 18:51

I maintain parallel Flash and HTML5/Canvas renderers for the OpenHeatMap open-source project. I\'m plagued by an inconsistency in the rendering of filled polygons with fract

相关标签:
3条回答
  • 2021-01-02 19:02

    I can see the same issue in Chrome 41.0.2272.89 m even when the coordinates are all integers: 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();
    

    I suspected that the problem might be caused by clockwise / counter-clockwise mismatch, as in some libraries I used to use in the past this would affect which edges are being drawn as solid, which as transparent, and which as antialiased. However, changing the order of lineTo() calls in the second triangle does not seem to have any effect.

    I've also tried chaning the fillStyle (the argument passed to fill()) from "evenodd" from the default "nonzero", with no luck.

    It's not clear for me from the spec https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-fill how this should work so I've filed the bug to learn more: https://www.w3.org/Bugs/Public/show_bug.cgi?id=28217

    0 讨论(0)
  • 2021-01-02 19:09

    This is an old question, but I had the same problem.

    I find that drawing a single line between the two polygons (or an outline around them) solves the problem (in firefox and chrome at least).

    That seems to fill the gap in chrome and firefox at least. It is sufficient to call ctx.stroke() after ctx.fill(), or draw a single line as follows:

    ctx.beginPath()
    ctx.moveTo(50.5, 0);
    ctx.lineTo(50.5, 100);
    ctx.stroke();
    

    and be sure to set the strokeStyle of course.

    0 讨论(0)
  • 2021-01-02 19:26

    Have you considered truncating all drawing coords? It shouldn't reduce quality, and it might fix your issue.

    You could also draw a line over the troubling area to make the issue invisible.

    If all else fails, that should work.

    0 讨论(0)
提交回复
热议问题