Почему артефакты видны в масштабированном холсте html5? - PullRequest
0 голосов
/ 15 сентября 2018

Я видел это и это обсуждение удаления антиалиасинга на полотнах, но я не думаю, что это одно и то же.

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

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

Как мне это исправить?Спасибо!

var example = document.getElementById("example");
var ctx = example.getContext('2d');

ctx.scale(1.13,1);

ctx.fillStyle = "LightGrey";
ctx.fillRect(10,10,50,30);

ctx.fillStyle = "Black";
ctx.font = "20px Arial";
ctx.fillText("< Looks good.",70,30);

ctx.fillStyle = "Red";
ctx.fillRect(10,50,50,30);

// This light grey rectangle should completely cover the previous red one, but it doesn't!
ctx.fillStyle = "LightGrey";
ctx.fillRect(10,50,50,30);

ctx.fillStyle = "Black";
ctx.font = "20px Arial";
ctx.fillText("< Do you see red?",70,70);
<canvas id="example"></canvas>

1 Ответ

0 голосов
/ 15 сентября 2018

Вы масштабируете матрицу преобразования в 1,13 раза по оси X.

Таким образом, ваша координата 10 фактически окажется в точке с координатой 11.3 в матрице реальных пикселей.

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

Так почему же первый выглядит лучше?

Потому что смесь серого и белого * более нейтральная, чем смесь красного серого и белого. Но даже ваш первый прямоугольник сглажен.

Просто увеличьте масштаб вашего холста, и вы увидите, что с обеих сторон полоса в один пиксель фактически полупрозрачна.

* "Белый" - это фон страницы

var example = document.createElement("canvas");
var ctx = example.getContext('2d');

ctx.scale(1.13,1);

ctx.fillStyle = "LightGrey";
ctx.fillRect(10,10,50,30);

ctx.fillStyle = "Red";
ctx.fillRect(10,50,50,30);

ctx.fillStyle = "LightGrey";
ctx.fillRect(10,50,50,30);

// draw bigger with no antialiasing
var z_ctx = zoomed.getContext('2d');
zoomed.width = example.width * 10;
zoomed.height = example.height * 10;
z_ctx.imageSmoothingEnabled = false;
z_ctx.drawImage(example, 0,0, zoomed.width, zoomed.height);
<canvas id="zoomed"></canvas>

Так как этого избежать?

Ну, просто избегайте заливки с нецелыми пиксельными координатами. Это означает, что вы также должны постоянно знать свою матрицу преобразования контекста, а не только значения, которые вы передаете функциям рисования.

(Ps: также помните, что инсульт - зверь-злодей, поскольку он начинает рисовать с середины линии, поэтому в этом случае вам даже нужно принять во внимание значение lineWidth, см. Q / A по данному вопросу).

...