Тег CANVAS: рисование на веб-странице (ч.2)

Автор: Topol Воскресенье, Май 6th, 2012 Нет комментариев

Рубрика: Операционные системы

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

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

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

 

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

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

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

Код:
ctx1.beginPath();

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

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

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

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

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

Параметры этого метода указывают координаты точки, в которую должно быть помещено перо. Результата этот метод не возвращает.

Код:
ctx1.moveTo(20, 20);

8.3. Рисование сегментов различной формы
Теперь рассмотрим, как рисуются разнообразные сегменты, составляющие контур сложной фигуры. К таким сегментам относятся прямые, дуги, кривые Безье различного типа и прямоугольники.

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

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

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

Код:
ctx1.moveTo(20, 20);
ctx1.lineTo(380, 280);

8.3.2. Рисование дуг
Дуги также рисуются довольно просто. Для этого применяется метод arc объекта CanvasRenderingContext2D. Вот формат его вызова:

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

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

    Код:
    величина в радианах = (Math.PI / 180) * величина в градусах;

    Свойство PI объекта Math хранит значение числа «пи».

  • Последний параметр указывает направление рисования души. Значение true указывает веб-браузеру нарисовать дугу против часовой стрелки, а значение false — по часовой стрелке.

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

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

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

Код:
ctx1.arc(200, 150, 100, 0, Math.PI, false);

Это выражение рисует дугу, представляющую собой половину окружности.

Код:
ctx1.arc(200, 150, 100, 0, 2 * Math.PI, false);

А это выражение рисует целую окружность.

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


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

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

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


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

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

Код:
контекст рисования.bezierCurveTo(
горизонтальная координата первой контрольной точки,
вертикальная координата первой контрольной точки,
горизонтальная координата второй контрольной точки,
вертикальная координата второй контрольной точки,
горизонтальная координата конечной точки,
вертикальная координата конечной точки
);

Назначение параметров этого метода понятно из их описания. Метод bezierCurveTo не возвращает результат.

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

Код:
ctx1.moveTo(100, 100);
ctx1.bezierCurveTo(120, 80, 260, 100, 60, 220);

Рисование кривых Безье с одной контрольной точкой выполняет метод quadraticCurveTo объекта CanvasRenderingContext2D. Формат его вызова таков:

Код:
контекст рисования.quadraticCurveTo(
горизонтальная координата контрольной точки,
вертикальная координата контрольной точки,
горизонтальная координата конечной точки,
вертикальная координата конечной точки
);

Назначение параметров этого метода понятно из их описания. Метод не возвращает результата.

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

Код:
ctx1.moveTo(100, 100);
ctx1.quadraticCurveTo(250, 50, 200, 200);

8.3.4. Рисование прямоугольников
Чтобы нарисовать прямоугольник в качестве сегмента контура сложной фигуры, следует использовать метод rect объекта CanvasRenderingContext2D.

Код:
контекст рисования.rect(
горизонтальная координата,
вертикальная координата,
ширина,
высота
);

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

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

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

Код:
ctxCanvas.rect(50, 50, 100, 150);

8.3.5. Автоматические замыкание контура
Если мы собираемся нарисовать сложную фигуру с заливкой, то должны будем закрыть её контур, то есть соединить его конечную точку с начальной какой-либо линией. Мы можем сделать это сами, а можем «попросить» сделать это за нас веб-браузер.

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

Код:
ctx1.closePath();

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

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

Код:
ctx1.stroke();

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

Код:
ctx1.fill();

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

Код:
ctx1.beginPath();
ctx1.moveTo(200, 20);
ctx1.lineTo(20, 280);
ctx1.lineTo(380, 280);
ctx1.closePath();
ctx1.stroke();

Этот код создаёт контур равностороннего треугольника. Отметим, что для его закрытия мы используем метод closePath — так проще.

Код:
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();

Этот код рисует три концентрические окружности без заливки.

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

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

Код:
ctx1.beginPath();
ctx1.moveTo(100, 100);
ctx1.quadraticCurveTo(300, 100, 300, 300);
ctx1.lineTo(100, 300);
ctx1.lineTo(100, 100);
ctx1.fill();

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

Код:
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();

А этот код рисует прямоугольник со скруглёнными углами без заливки. Для создания скруглённых углов используются кривые Безье с одной контрольной точкой.

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

Источник: thevista.ru

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты