Как избежать артефактов сшивания краев многоугольника в HTML5 Canvas? - PullRequest
7 голосов
/ 31 января 2011

Я поддерживаю параллельные Flash и HTML5 / Canvas рендеры для проекта OpenHeatMap с открытым исходным кодом.Меня мучает несогласованность в рендеринге заполненных полигонов с дробными координатами между двумя версиями.Если вы визуализируете два многоугольника, которые имеют общий край, Canvas покажет видимое соединение вдоль этого края, тогда как Flash будет плавно объединять их вместе без видимой разницы, если они одного цвета.Я собрал здесь минимальную страницу, чтобы показать проблему:

http://web.mailana.com/labs/stitchingbug/

[Гак, защита от спама не дает возможности быть изображением, но посмотрите здесь для скриншота web.mailana.com / labs / stitchingbug.png]

Источник, вместе с Flash-проектом, который делает то же самое, находится здесь:

github.com / petewarden / stitchingbug

Фундаментальная проблема заключается в том, что невозможно выполнить сложную многоугольную визуализацию, если вы не можете сшивать многоугольники без швов.Я точно не знаю, каковы правила заполнения Flash, но они дают правильные результаты, как и 3D-рендеры.У кого-нибудь есть исправление на стороне клиента, чтобы обойти эту проблему?Это кросс-браузер, что делает его преднамеренным, поэтому любые ссылки на используемые правила также приветствуются.Вот код холста:

    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();

Ответы [ 3 ]

3 голосов
/ 27 июня 2012

Это старый вопрос, но у меня была такая же проблема.

Я считаю, что рисование одной линии между двумя полигонами (или контур вокруг них) решает проблему (по крайней мере, в Firefox и Chrome).

Это, кажется, заполняет пробел в Chrome и Firefox по крайней мере. Достаточно позвонить ctx.stroke() после ctx.fill() или нарисовать одну линию следующим образом:

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

и, конечно же, обязательно установите значение strokeStyle.

1 голос
/ 15 марта 2015

Я вижу ту же проблему в Chrome 41.0.2272.89 м, даже когда все координаты целые: 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 () во втором треугольнике, похоже, не имеет никакого эффекта.

Я также попытался изменить fillStyle (аргумент, переданный функции fill ()) из "evenodd" изпо умолчанию "nonzero", без удачи.

Из спецификации https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-fill мне не ясно, как это должно работать, поэтому я подал ошибку, чтобы узнать больше: https://www.w3.org/Bugs/Public/show_bug.cgi?id=28217

1 голос
/ 31 января 2011

Рассматривали ли вы усечение всех координат рисования? Это не должно снижать качество и может решить вашу проблему.

Вы также можете нарисовать линию над проблемной областью, чтобы сделать проблему невидимой.

Если ничего не помогает, это должно сработать.

...