Можно ли отключить сглаживание элемента HTML <canvas>?

Я играю с элементом <canvas>, рисованием строк и т.д.

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

Ответ 1

Для изображений теперь context.imageSmoothingEnabled = false.

Однако нет ничего, что явно контролирует рисование линии. Вам может потребоваться нарисовать собственные строки (трудный путь) с помощью getImageData и putImageData.

Ответ 2

Нарисуйте ваши строки 1-pixel на координатах, таких как ctx.lineTo(10.5, 10.5). Рисование однопиксельной линии над точкой (10, 10) означает, что этот пиксель 1 в этом положении достигает от 9.5 до 10.5, что приводит к двум строкам, которые нарисованы на холсте.

Хороший трюк, который не всегда должен добавить 0.5 к фактической координате, которую вы хотите нарисовать, если у вас много однопиксельных линий, - это ctx.translate(0.5, 0.5) весь ваш холст в начале.

Ответ 3

Это можно сделать в Mozilla Firefox. Добавьте это в свой код:

contextXYZ.mozImageSmoothingEnabled = false;

В Opera это запрос функции, но, надеюсь, он будет добавлен в ближайшее время.

Ответ 4

Он должен сглаживать векторную графику

Сглаживание требуется для правильной компоновки векторной графики, которая включает в себя нецелые координаты (0,4, 0,4), которые будут делать только очень мало клиентов.

При задании нецелых координат холст имеет два варианта:

  • Сглаживание - нарисуйте пиксели вокруг координаты относительно того, насколько далеко целочисленная координата от нецелого одного (ошибка округления).
  • Round - примените некоторую функцию округления к нецелочисленной координате (таким образом, 1.4 станет 1, например).

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

Реальная проблема заключается в том, когда графика переведена (перемещена) - переходы между одним пикселем и другим (1.6 = > 2, 1.4 = > 1) означают, что начало формы может скачкообразно сказываться относительно родительского контейнера (постоянно смещая 1 пиксель вверх/вниз и влево/вправо).

Некоторые советы

Совет № 1. Вы можете смягчить (или затвердеть) сглаживание, масштабируя холст (скажем, x), затем примените обратную шкалу (1/x) к геометриям самостоятельно (не используя холст).

Сравнить (без масштабирования):

Несколько прямоугольников

с (масштаб холста: 0,75, ручная шкала: 1,33):

Те же прямоугольники с более мягкими краями

и (масштаб холста: 1,33, ручная шкала: 0,75):

Те же прямоугольники с более темными краями

Совет № 2. Если вам не понравился внешний вид, попробуйте рисовать каждую фигуру несколько раз (без стирания). С каждой ничьей пиксели сглаживания становятся более темными.

Сравнить. После однократного рисования:

Несколько путей

После трехкратного рисования:

Те же пути, но темнее и нет видимого сглаживания.

Ответ 5

Я бы рисовал все, используя собственный алгоритм линии, такой как алгоритм линии Bresenham. Проверьте эту реализацию javascript: http://members.chello.at/easyfilter/canvas.html

Я думаю, что это определенно решит ваши проблемы.

Ответ 6

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

Я решил использовать это:

function setpixelated(context){
    context['imageSmoothingEnabled'] = false;       /* standard */
    context['mozImageSmoothingEnabled'] = false;    /* Firefox */
    context['oImageSmoothingEnabled'] = false;      /* Opera */
    context['webkitImageSmoothingEnabled'] = false; /* Safari */
    context['msImageSmoothingEnabled'] = false;     /* IE */
}

Вы можете использовать эту функцию следующим образом:

var canvas = document.getElementById('mycanvas')
setpixelated(canvas.getContext('2d'))

Возможно, это полезно для кого-то.

Ответ 7

ctx.translate(0.5, 0.5);
ctx.lineWidth = .5;

С помощью этой комбинации я могу нарисовать красивые тонкие линии 1px.

Ответ 8

Обратите внимание на очень ограниченный трюк. Если вы хотите создать изображение с 2 цветами, вы можете нарисовать любую фигуру с цветом # 010101 на фоне с цветом # 000000. Как только это будет сделано, вы можете протестировать каждый пиксель в файле imageData.data [] и установить в 0xFF любое значение не 0x00:

imageData = context2d.getImageData (0, 0, g.width, g.height);
for (i = 0; i != imageData.data.length; i ++) {
    if (imageData.data[i] != 0x00)
        imageData.data[i] = 0xFF;
}
context2d.putImageData (imageData, 0, 0);

Результатом будет неэлеализированное черно-белое изображение. Это будет не идеально, так как некоторое сглаживание будет иметь место, но это сглаживание будет очень ограниченным, цвет формы очень похож на цвет фона.