Опрос
Вы участвуете в программе Windows Insider?
Популярные новости
Обсуждаемые новости

25.02.2011 12:01 | dronov_va

Продолжаем рассматривать канву HTML 5 - средство для программного рисования прямо на веб-странице.


8. Рисование сложных фигур
Но чтобы нарисовать более-менее сложную картинку, одних только прямоугольников недостаточно. Поэтому канва предоставляет нам средства для рисования сложных фигур, контур которых состоит из произвольного количества сегментов - прямых и кривых линий, соединённых друг с другом. Сейчас мы узнаем, как пользоваться этими средствами.

Вообще, все сложные фигуры рисуются в три этапа:

  • Веб-браузер ставится в известность, что сейчас мы начнём рисовать контур сложной фигуры.
  • Рисуются отдельные сегменты контура этой фигуры.
  • Веб-браузер ставится в известность, что рисование контура закончено, и теперь фигура должна быть выведена на канву, возможно, с заливкой.


Рассмотрим все эти три этапа более подробно.

8.1. Начало рисования сложной фигуры
Сначала, как уже говорилось, нам следует поставить веб-барузер в известность о том, что сейчас мы начнём рисовать контур сложной фигуры. Для этого достаточно вызвать метод beginPath объекта CanvasRenderingContext2D. Этот метод не принимает параметров и не возвращает результата.

ctx1.beginPath();


Теперь мы можем начинать рисование контура сложной фигуры.

8.2. Перо. Перемещение пера
При рисовании контуров сложных фигур используется концепция пера. Перо - это воображаемый инструмент, с помощью которого и рисуются отдельные сегменты контура.

  • Изначально перо находится в точке с координатами [0, 0], то есть в начале координат канвы (в её верхнем левом углу).
  • Рисование любого сегмента начинается в точке, где в текущий момент находится перо.
  • По окончании рисования сегмента перо окажется в его конечной точке. Из этой точки мы можем начать рисование следующего сегмента контура. (Из этого правла есть исключения, о которых мы обязательно поговорим.)
  • Мы можем перемещать перо в произвольную точку канвы.


Чтобы переместить перо в другую точку канвы, следует вызвать метод moveTo объекта CanvasRenderingContext2D. Вот формат его вызова:

контекст рисования.moveTo(
  горизонтальная координата,
  вертикальная координата>
);

ата,
вертикальная координата>
);[/code]
Параметры этого метода указывают координаты точки, в которую должно быть помещено перо. Результата этот метод не возвращает.

[code]ctx1.moveTo(20, 20);[/code]
8.3. Рисование сегментов различной формы
Теперь рассмотрим, как рисуются разнообразные сегменты, составляющие контур сложной фигуры. К таким сегментам относятся прямые, дуги, кривые Безье различного типа и прямоугольники.

8.3.1. Рисование прямых линий
Прямые линии рисовать проще всего. Для этого используется метод lineTo объекта CanvasRenderingContext2D. Формат его вызова выглядит так:

[code]контекст рисования.lineTo(
горизонтальная координата,
вертикальная координата>
);[/code]
Прямая, что мы нарисуем, начнётся в точке, где сейчас располагается перо, и закончится в точке, чьи координаты указаны в параметрах этого метода. Результата он не возвращает.

[code]ctx1.moveTo(20, 20);
ctx1.lineTo(380, 280);[/code]
8.3.2. Рисование дуг
Дуги также рисуются довольно просто. Для этого применяется метод arc объекта CanvasRenderingContext2D. Вот формат его вызова:

[code]контекст рисования.arc(
горизонтальная координата центра,
вертикальная координата центра,
радиус,
начальный угол,
конечный угол,
направление рисования
);[/code]

  • Первые два параметра указывают координаты центра дуги.
  • Третий параметр указывает радиус дуги в виде числа в пикселах.
  • Четвёртый и пятый параметры указывают начальный и конечный углы дуги в виде чисел в радианах. Эти углы отсчитываются от горизонтальной оси.

    Чтобы пересчитать градусы в радианы, следует использовать выражение вида:

    [code]величина в радианах = (Math.PI / 180) * величина в градусах;[/code]
    Свойство PI объекта Math хранит значение числа "пи".
  • Последний параметр указывает направление рисования души. Значение true указывает веб-браузеру нарисовать дугу против часовой стрелки, а значение false - по часовой стрелке.


Результата метод arc не возвращает.

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

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

[code]ctx1.arc(200, 150, 100, 0, Math.PI, false);[/code]
Это выражение рисует дугу, представляющую собой половину окружности.

[code]ctx1.arc(200, 150, 100, 0, 2 * Math.PI, false);[/code]
А это выражение рисует целую окружность.

8.3.3. Рисование кривых Безье
Кривые Безье - это линии особой формы, описываемые тремя или четырьмя точками: начальной, конечной и одной или двумя контрольными. Начальная и конечная точки, как и в случае прямой линии, задают начало и конец кривой Безье, а контрольные точки формируют касательные, определяющие форму этой кривой.


Рис. 1. Кривая Безье с двумя контрольными точками


Кривая Безье с двумя контрольными точками представлена на рис. 1. Сама она показана в виде толстой линии. Её начальная и конечная точки обозначены кружками, а контрольные точки - квадратиками. Через каждую контрольную точку и начальную и конечную точку кривой Безье проведены касательные (тонкие прямые линии) — они определяют форму кривой. Если мы мысленно переместим какую-либо из контрольных точек, то форма проведённой через неё касательной изменится, и, следовательно, кривая Безье примет другую форму.

Существует и другой вид кривых Безье — с одной контрольной точкой (рис. 2).


Рис. 2. Кривая Безье с одной контрольной точкой


Для рисования кривых Безье с двумя контрольными точками служит метод bezierCurveTo объекта CanvasRenderingContext2D. Формат его вызова выглядит так:

[code]контекст рисования.bezierCurveTo(
горизонтальная координата первой контрольной точки,
вертикальная координата первой контрольной точки,
горизонтальная координата второй контрольной точки,
вертикальная координата второй контрольной точки,
горизонтальная координата конечной точки,
вертикальная координата конечной точки
);[/code]
Назначение параметров этого метода понятно из их описания. Метод bezierCurveTo не возвращает результат.

Рисование кривой Безье начинается в той точке, где в данный момент находится перо. После рисования кривой перо устанавливается в её конечную точку.

[code]ctx1.moveTo(100, 100);
ctx1.bezierCurveTo(120, 80, 260, 100, 60, 220);[/code]
Рисование кривых Безье с одной контрольной точкой выполняет метод quadraticCurveTo объекта CanvasRenderingContext2D. Формат его вызова таков:

[code]контекст рисования.quadraticCurveTo(
горизонтальная координата контрольной точки,
вертикальная координата контрольной точки,
горизонтальная координата конечной точки,
вертикальная координата конечной точки
);[/code]
Назначение параметров этого метода понятно из их описания. Метод не возвращает результата.

И здесь рисование кривой Безье начинается в той точке, где в данный момент установлено перо. После рисования кривой перо устанавливается в её конечную точку.

[code]ctx1.moveTo(100, 100);
ctx1.quadraticCurveTo(250, 50, 200, 200);[/code]
8.3.4. Рисование прямоугольников
Чтобы нарисовать прямоугольник в качестве сегмента контура сложной фигуры, следует использовать метод rect объекта CanvasRenderingContext2D.

[code]контекст рисования.rect(
горизонтальная координата,
вертикальная координата,
ширина,
высота
);[/code]
Первые два параметра задают, соответственно, горизонтальную и вертикальную координаты верхнего левого угла рисуемого прямоугольника, а третий и четвёртый - его ширину и высоту. Результата этот метод не возвращает.

Метод rect стоит несколько особняком. Дело в том, что он не соединяет только что созданный прямоугольник с нарисованными ранее сегментами. То есть прямоугольник, что мы создали с помощью этого метода, скажем так, "повисает в пространстве".

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

[code]ctxCanvas.rect(50, 50, 100, 150);[/code]
8.3.5. Автоматические замыкание контура
Если мы собираемся нарисовать сложную фигуру с заливкой, то должны будем закрыть её контур, то есть соединить его конечную точку с начальной какой-либо линией. Мы можем сделать это сами, а можем "попросить" сделать это за нас веб-браузер.

Вызов метода closePath объекта CanvasRenderingContext2D автоматически закрывает контур прямой линией. Этот метод не принимает параметров и не возвращает результата.

[code]ctx1.closePath();[/code]

8.4. Завершение рисования сложной фигуры
Нарисовав контур сложной фигуры и, возможно, закрыв его, вручную или вызовом метода closePath, мы должны указать веб-браузеру, что рисование, собственно, закончено, и готовую фигуру следует вывести на канву. Для этого применяются два метода, которые мы сейчас рассмотрим.

Метод stroke объекта CanvasRenderingContext2D просто завершает рисование контура сложной фигуры. Он не принимает параметров и не возвращает результата.

[code]ctx1.stroke();[/code]
Метод fill объекта CanvasRenderingContext2D завершает рисование контура сложной фигуры и создаёт для неё заливку. Он также не принимает параметров и не возвращает результата.

[code]ctx1.fill();[/code]

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

[code]ctx1.beginPath();
ctx1.moveTo(200, 20);
ctx1.lineTo(20, 280);
ctx1.lineTo(380, 280);
ctx1.closePath();
ctx1.stroke();[/code]
Этот код создаёт контур равностороннего треугольника. Отметим, что для его закрытия мы используем метод closePath - так проще.

[code]ctx1.beginPath();
ctx1.arc(200, 150, 150, 0, Math.PI * 2, false);
ctx1.moveTo(300, 150);
ctx1.arc(200, 150, 100, 0, Math.PI * 2, false);
ctx1.moveTo(250, 150);
ctx1.arc(200, 150, 50, 0, Math.PI * 2, false);
ctx1.stroke();[/code]
Этот код рисует три концентрические окружности без заливки.

Здесь у нас возникает проблема. Дело в том, что метод arc при рисовании дуги (а окружность - та же дуга) соединяет её начальную точку с точкой, где в данный момент находится перо, прямой линией. А перо после рисования предыдущей дуги окажется в её конечной точке. О начальных и конечных точках дуг см. в параграфе 8.3.2. В результате мы увидим в окне веб-браузера прямые линии, соединяющие начальные точки всех трёх окружностей.

Чтобы избежать этого, мы принудительно устанавливаем перо в то место на канве, где будут находиться начальные точки второй и третьей рисуемых нами окружностей; это делают вызовы метода moveTo в приведённом выше коде. Горизонтальная координата этих точек в нашем случае (то есть при нулевом начальном угле) будет равна сумме горизонтальной координаты центра окружности и её радиуса, а вертикальная координата будет равна вертикальной координате центра окружности.

[code]ctx1.beginPath();
ctx1.moveTo(100, 100);
ctx1.quadraticCurveTo(300, 100, 300, 300);
ctx1.lineTo(100, 300);
ctx1.lineTo(100, 100);
ctx1.fill();[/code]
Этот код рисует сектор окружности с заливкой, формируя его из кривой Безье с одной контрольной точкой и двух прямых линий.

[code]ctx1.beginPath();
ctx1.moveTo(20, 0);
ctx1.lineTo(280, 0);
ctx1.quadraticCurveTo(300, 0, 300, 20);
ctx1.lineTo(300, 180);
ctx1.quadraticCurveTo(300, 200, 280, 200);
ctx1.lineTo(20, 200);
ctx1.quadraticCurveTo(0, 200, 0, 180);
ctx1.lineTo(0, 20);
ctx1.quadraticCurveTo(0, 0, 20, 0);
ctx1.stroke();[/code]
А этот код рисует прямоугольник со скруглёнными углами без заливки. Для создания скруглённых углов используются кривые Безье с одной контрольной точкой.

Продолжение следует...


dronov_va, TheVista.Ru Team
Февраль 2011

Комментарии

Не в сети

опять в некоторых местах bb коды)
Ну а в целом хорошо

25.02.11 13:11
0
Для возможности комментировать войдите в 1 клик через

По теме

Акции MSFT
420.55 0.00
Акции торгуются с 17:30 до 00:00 по Москве
Все права принадлежат © ms insider @thevista.ru, 2022
Сайт является источником уникальной информации о семействе операционных систем Windows и других продуктах Microsoft. Перепечатка материалов возможна только с разрешения редакции.
Работает на WMS 2.34 (Страница создана за 0.163 секунд (Общее время SQL: 0.142 секунд - SQL запросов: 55 - Среднее время SQL: 0.00258 секунд))
Top.Mail.Ru