2015-12-17 3 views
5

Я играл с элементом холста и обнаружил, что при попытке нарисовать NxN однородные сплошные ячейки рядом друг с другом, в некоторых конфигурациях ширины и высоты существуют размытые белые линии между их.Weird HTML 5 Canvas Antialiasing

Например, этот холст должен выглядеть черным, но содержит сетку , которая, как я предполагаю, является результатом ошибочного сглаживания в браузере.

The canvas demonstrating the issue.

Достаточно сказать, что эта ошибка появляется только в некоторых конфигурации, но я хотел бы избавиться от него навсегда. Есть ли способ обойти это? Были ли у вас проблемы с сглаживанием в холсте?

Я сделал this fiddle, что демонстрирует проблему и позволяет вам играть с размерами холста и количества ячеек. Он также содержит код, который я использую для рисования ячеек, чтобы вы могли проверить его и сказать мне, что я делаю что-то неправильно.

var ctx = canvas.getContext('2d'); 
ctx.clearRect(0, 0, canvasWidth, canvasHeight); 
for (var i = 0; i < numberOfCells; ++i) { 
    for (var j = 0; j < numberOfCells; ++j) { 
    ctx.fillStyle = '#000'; 
    ctx.fillRect(j * cellWidth, i * cellHeight, cellWidth, cellHeight); 
    } 
} 

Спасибо заранее,

Петр.

+0

Здравствуйте Петр, казалось бы, вы забыли предоставить свою ссылку скрипку, могли бы вы обновить – Canvas

+0

Просто заметил. Извините, здесь вы идете! :) –

+0

Общим трюком является преобразование всего холста на один пиксель в начале, чтобы увернуться от этого, я считаю. –

ответ

1

После прочтения и попыток нескольких подходов я решил придумать свои собственные. Я создал другой (виртуальный) холст, который имел целочисленные размеры, соответствующие количеству ячеек в сетке.

После рисования всех ячеек, я вызываю context.drawImage() на основном холсте и передаю виртуальный холст в качестве аргумента, а также параметры смещения и масштаба, чтобы он соответствовал остальной части моего рисунка. Предполагая, что браузер будет масштабировать изображение виртуального холста в целом (а не отдельные ячейки), я надеялся избавиться от нежелательных разделительных линий.

Несмотря на мои усилия, линии все еще существуют. Какие-либо предложения?

Вот скрипка демонстрирует свою технику: https://jsfiddle.net/ngxjnywz/5/

+0

Я обнаружил преступника. Оказывается, этот подход работает до тех пор, пока я не перемещаю вторичный холст на 0,5 пиксела (как было предложено в другом ответе). После удаления 'context.translate (0.5, 0.5)' все остальное встало на свои места. –

4

jsFiddle: https://jsfiddle.net/ngxjnywz/2/

фрагмент JavaScript

var cellWidth = Math.ceil(canvasWidth/numberOfCells); 
var cellHeight = Math.ceil(canvasHeight/numberOfCells); 

В зависимости от ширины, высоты и ваши numberOfCells вы иногда получаете ... позволяет сказать, что 4.2, который 4, однако это будет отображаться неправильно и позволит создать пустую строку размером 1 пиксель. Таким образом, все, что вам нужно сделать, это использовать функцию Math.ceil, и это приведет к тому, что ваш cellWidth и cellHeight всегда будут больше, и вы больше не получите пустых строк.

+0

К сожалению, округление работает только в том случае, если линии параллельны оси X или Y, и не учитывает любые преобразования, которые могут применяется. – Blindman67

+0

Это действительно приятное и легкое решение. Это может стать немного беспорядочным, так как ячейки начнут перекрываться, и это может привести к тому, что порядок рисования станет действительно актуальным, но поскольку для смещения процедуры рисования будет использована такая же предельная «cellWidth», это будет предотвращено. –

+0

Я только что попробовал «ctx.fillRect (j * cellWidth + 151, i * cellHeight + 77, cellWidth, cellHeight); и он работает без проблем, однако я могу подтвердить, что любое «преобразование» в сетке будет воспроизводить строки, однако если вы измените что-либо после того, как сетка будет в порядке, взгляните на мою ссылку https://jsfiddle.net/ngxjnywz/ 4/ – Canvas

2

Лучшее решение - добавить ход на 0,5 пикселя вокруг все заливки, используя тот же стиль, что и заполнение и смещение всего чертежа, чтобы вы отображали в центре пикселей, а не в верхнем левом углу.

Если вы добавили масштабирование или перевод, вам придется отрегулировать координаты так, чтобы вы по-прежнему предоставляли центры для ваших графических координат.

В конце вы можете только уменьшить артефакты, но для многих ситуаций вы не сможете полностью их удалить.

Этот ответ показывает, как удалить артефакты для нетрансформированного холста. How to fill the gaps

+0

Это довольно сложная процедура. В моей конкретной установке мне пришлось бы полностью переосмыслить математику моего рисования сетки. –

+0

@ PetrMánek True, но в других ситуациях это действительно самое простое решение - просто добавьте .5 ко всем координатам. –

+0

@ PetrMánek. Полупиксельный трюк хорошо работает за счет некоторой редизайна. Другим обходным решением является создание «строительных блоков» на втором холсте и [сборка вашего проекта из этих строительных блоков] (http://stackoverflow.com/questions/29355920/canvas-polygons-not-touching-properly) – markE