В Html5 нарисуйте от (0,5, 0) до (0,5, 600), чтобы получить на холсте линию толщиной в 1 пиксель. 0,5 странно? - PullRequest
5 голосов
/ 07 сентября 2010

Я читаю книгу на Html5 и о канве, следующий код будет генерировать строки толщиной в 1 пиксель ... Он использует 0,5 в качестве координаты. Если оно будет изменено на 0 или 10, или на какое-то целое число, то линии будут серыми и толщиной в 2 пикселя. Это почему? Это самая странная вещь, которую я видел в последнее время ... все программирование до этого на Apple или Win32 API, они идут по целочисленным координатам.

<!DOCTYPE html>

<body>
<canvas id="c" width="800" height="600"></canvas>
</body>

<script>

var c_canvas = document.getElementById("c")
var context = c_canvas.getContext("2d")

for (x = 0.5; x < 500; x += 10) {
  context.moveTo(x, 0)
  context.lineTo(x, 375)
}
context.strokeStyle = "#000"
context.stroke()


</script>

Еще одна странная вещь: чтобы получить черную точку 1 на 1 пиксель, мне нужно нарисовать 0,5 для x, но использовать целые числа для y

for (x = 0.5; x < 500; x += 10) {
  context.moveTo(x, 0)
  context.lineTo(x, 1)
}

если я использую следующее, то я получаю серую "длинную точку"

for (x = 0.5; x < 500; x += 10) {
  context.moveTo(x, 0.5)
  context.lineTo(x, 1.5)
}

Ответы [ 4 ]

11 голосов
/ 07 сентября 2010

Спасибо, МиКы.Я также нашел какое-то объяснение:

https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors#A_lineWidth_example

Это релевантное содержание:

Для получения четких линий необходимо понять, как обводятся контуры.На изображениях ниже сетка представляет собой координатную сетку холста.Квадраты между линиями сетки являются фактическими пикселями на экране.На первом изображении сетки ниже прямоугольник от (2,1) до (5,5) заполнен.Вся область между ними (светло-красная) попадает на границы пикселей, поэтому результирующий закрашенный прямоугольник будет иметь четкие края.

Crisp and Blurry lines example

Если вы рассматриваете путьот (3,1) до (3,5) с толщиной линии 1,0, вы получите ситуацию на втором изображении.Фактическая область, которая должна быть заполнена (темно-синяя), простирается только наполовину в пикселях по обе стороны от пути.Приближение этого должно быть отображено, что означает, что эти пиксели только частично заштрихованы, и в результате вся область (светло-синий и темно-синий) будет заполнена цветом, только наполовину темнее, чем фактический цвет обводки.Это то, что происходит со строкой ширины 1,0 в предыдущем примере кода.

Чтобы это исправить, вы должны быть очень точными в создании пути.Зная, что линия шириной 1,0 простирается на половину единицы по обе стороны от пути, создание пути от (3,5,1) до (3,5,5) приводит к ситуации на третьем изображении - ширина линии 1,0 заканчивается полностью иточное заполнение вертикальной линии одного пикселя.

6 голосов
/ 07 сентября 2010

Я не уверен, что это то же самое с HTML5, но это выглядит очень похоже на то, как библиотека Qt работает с рисованием. По сути, координаты (0,0) и (1,1) определяют пиксель в верхнем левом углу - его центр, таким образом, находится в точке (0,5, 0,5).

Это связано с сглаживанием - если вы «нарисуете» черный пиксель в точке (1,1), 4 серых пикселя будут фактически окрашены в серый цвет между (0,0) и (2,2). Подробнее об этом читайте в программировании на C ++ с использованием Qt 4 .

2 голосов
/ 07 сентября 2010

В двух словах, пиксели не могут быть разделены. Когда вы используете lineTo для рисования линии в 1 пиксель, линия центрируется по указанной вами координате. Если width = 1 и координата является целым числом, то вы просите нарисовать 2 половинки пикселя.

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

0 голосов
/ 10 марта 2015

Я более или менее борюсь с этим, когда когда-нибудь через какое-то время снова начинаю использовать canvas - вы работаете с «математическими» линиями, а не линиями на экране.

Как уже упоминалось, строка от (1,1) до (1,10) начинается между пикселями (0/0, 1/1) и заканчивается между (0/10, 1/11)

так что его 1 пиксель в ширину и 1 пиксель в высоту. но приятно немного светлее ...

Мое решение, если вы используете холст для рисования только "жестких целочисленных линий", например, для создания элемента управления используется transform(1,0,0,1,0.5,0.5) (или transform(1,0,0,1,-0.5,-0.5) зависит от того, хотите ли вы запустить его с 0 или 1)

(я использую преобразование, чтобы убедиться, что нет (a) или (d), что снова усложнит мне жизнь)

просто сдвиньте ноль на строке «между 0 и 1» (теперь вы знаете мой ник ...)

Это прекрасно работает во всех моих случаях, когда я рисую (или должен рисовать) "pixeled"

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