Одной из интересных возможностей нового стандарта HTML5 является элемент ‹canvas›, или холст. Холст предназначен для создания (именно, создания) растровых изображений на странице средствами графического движка браузера. Canvas способен изображать не только статические, но и динамические изображения (анимацию).

До появления canvas для вставки анимации могли спользоваться gif-изображения, flash-анимация или, основанные на скриптах или других подключаемых модулях, другие решения (в частности Silverlight, Java Applets, ActiveX и другие). Однако, каждое из этих решений имеет ряд недостатков. Например, плохое качество анимации gif-изображений, большой размер загружаемых модулей Java, несоответствие версий Flash проигрывателя, ActiveX работает исключительно в Internet Explorer и многое другое. Но главным фактором появления анимации и графики на основе canvas является высокий рост мобильного сегмента Интернет, особенно устройств типа iPhone, iPod touch, iPad, а также различных устройств под управлением Android. Установить плагин на них нет возможности, а i-устройства не поддерживают Flash (а начиная с версии 4.0 его также не поддерживают устройства под управлением Android).

Поэтому для поддержки огромной доли рынка мобильных устройств с возможностью подключения к сети Интернет анимацию начали создавать при помощи javascript. Для этого обычно используют библиотеки, как например jQuery или Prototype. C введением в действие стандарта CSS3 часть анимаций возможно создавать с помощью каскадных таблиц стилей. Однако самыми широкими возможностями по созданию изображений и анимаций пользуется стандарт HTML5 и его новый элемент ‹canvas›.

Элемент ‹canvas›

‹canvas› - это новый элемент HTML5, который позволяет создавать изображения на сайте с помощью javascript. Область использования холстов довольно широкая. Чаще всего его можно увидеть при создании деловой графики (чарты, диаграмы, графики), а также для рендеринга браузерных игр (чаще всего встречаются в социальных сетях). У ‹canvas› есть только 2 атрибута – ширина и высота. Если эти атрибуты отсутсвуют, то ширина по умолчанию будет равна 300 пикселей, а высота 150 пикселей.

Элемент ‹canvas› создает контекст отрисовки, на котором в будущем можно создавать и манипулировать объектами javascript. Другими словами, ‹canvas› представляет собой прямоугольную область, в которой с помощью javascript можно "рисовать".

На сегодняшний день стандарт полностью описывает работу двумерных контекстов (для плоской графики, 2D). Однако, сейчас проводится работа по разработке стандарта WebGL, для поддержки элементом ‹canvas› трехмерных контекстов (примеры работ можно посмотреть в Лаборатории Chrome).

Для размещения элемента на странице HTML достаточно указать:

‹canvas width=600 height=250› ‹/canvas› 

После помещения на страницу элементом ‹canvas› можно манипулировать как угодно: помещать на него текст, рисовать графические элементы и линии, выполнять заливку, добавлять анимацию. Все это делается при помощи команд javascript. Чтобы использовать холст программным путем необходимо прежде всего получить доступ к его контексту. После этого выполняются все необходимые действия с контекстом и только тогда результат подтверждается и выводится на холст. То есть, сначала изображение создается программно, а потом результат выводится визуально.

Так как не все браузеры поддерживают HTML5, то на данное время воспользоваться ‹canvas› можно только в следующих браузерах (по информации caniuse.com):

  • Internet Explorer 9+
  • Firefox 2.0+
  • Chrome 4+
  • Safari 3.1+
  • Opera 9.0+
  • iOS 3.2+
  • Android 2.1+

В случае, если к ‹canvas› обратились из браузера, который не поддерживает этот элемент, то пользователь увидит содержимое, помещенное внутри этого тега (такое содержимое называют аварийным), например:

‹canvas› Your browser is not support HTML5 Canvas! Please update your browser version! ‹/canvas› 

Рисование на холсте

Перед тем, как начать рисовать, нужно получить от браузера контекст холста, то есть экземпляр объекта CanvasRenderingContext2D. Сделать это можно следующим образом:

var canvas = document.getElementById("canvas");   
var context = canvas.getContext("2d");

В первой строке мы получам сам холст, а во второй с помощью вызова единственного метода объекта холста getContext() получаем контекст этого холста. Параметр 2D указывает на то, что получаемый нами контекст будет создавать плоское изображение (экземпляр объекта CanvasRenderingContext2D).

Теперь можно приступить к рисованию. Следует помнить, что для рисования с помощью ‹canvas› потребуется понимание системы координат, где каждой точкой является пиксель на экране, а началом координат является верхний левый угол холста. Создадим новый холст, зададим для него атрибут id=canvas и добавим к нему рабочку, чтобы было удобнее следить за результатом:

‹canvas width=150 height=150 style="border:1px solid #ccc;" id=canvas› ‹/canvas›

Результат вы можете видеть ниже:

Для иллюстрации примеров будем использовать функцию CreateImage(), которая вызывается при загрузке страницы:

function CreateImage() {
   var cnvs = document.getElementById("canvas");
   var ctxt = canvas.getContext("2d");
} 

Прямоугольники

Для отображения прямоугольных фигур используются следующие методы:

  • strokeRect(x, y, width, height) - создает прямоугольник без заливки, где x и y - координаты верхнего левого угла прямоугольника, а width и height - соответственно ширина и высота прямоугольника
  • fillRect(x, y, width, height) - создает прямоугольник с заливкой. Значения параметров аналогичны методу strokeRect
  • clearRect(x, y, width, height) - очищает прямоугольную область. Значения параметров аналогичны методу strokeRect

Изменим функцию CreateImage() для демонстрации рисования двух прямоугольников:

function CreateImage() {
   var cnvs = document.getElementById("canvas");
   var ctxt = canvas.getContext("2d");
   ctxt.strokeRect(20,20,50,70);
   ctxt.fillRect(90,90,60,45);
} 

Результат:

Если в код функции CreateImage()добавить строку

   ctxt.clearRect(45,50,60,75);

То получится следующий результат:

Работа с цветом и толщиной линий

Изменять свойства пера, то есть цвет и толщину линий, можно изменяя свойства экземпляра обекта контекста CanvasRenderingContext2D. Для этих целей существуют следующие свойства:

  • strokeStyle - задает цвет линии контура. Все объекты, которые будут нарисованы позже будут иметь цвет контура, указанный этим свойством. Сам цвет задается в одном из форматов цвета CSS3. Например, rgba(r, g, b, a) или #RRGGBB. Могут использоваться и константы
  • fillStyle - это свойство задает цвет заливки внутри контура. Все объекты, которые будут нарисованы позже будут иметь цвет заливки, указанный этим свойством. Аналогично, цвет задается в формате CSS3
  • lineWidth - это свойство задает толщину линии в пикселях

Следует учитывать, что нельзя назначать свойству strokeStyle значение свойства fillStyle и наооборот - это вызовет ошибку в скрипте. Добавим эти свойства в наш пример:

function CreateImage() {
   var cnvs = document.getElementById("canvas");
   var ctxt = canvas.getContext("2d");
   ctxt.strokeStyle = "#CC4F21";
   ctxt.lineWidth = 10;
   ctxt.strokeRect(20,20,50,70);
   ctxt.strokeStyle = "green";
   ctxt.strokeStyle = "rgba(152, 28, 96, 0.5";
   ctxt.fillRect(90,90,60,45);
   ctxt.clearRect(45,50,60,75);
} 

Результат ниже:

 

Работа с пером

Рисование более сложных объектов производится с помощью виртуального "пера". Для работы с ним существует ряд методов. Прежде всего нужно понять разницу между двумя основными методами:

  • moveTo(x,y) - смещает перо в точку с координатами x, y (перо поднято)
  • lineTo(x,y) - рисует линию из текущей координаты пера в точку с координатами x, y (перо опущено)

Изначально перо находится в начале коордиант - верхнем левом углу холста.

Начало рисования сложной линии должно начинаться вызовом метода beginPath(), а конец stroke(). Для того, чтобы замкнуть фигуру можно воспользоваться вызовом метода closePath(). Замкнутую фигуру можно залить цветом. Для этого вместо stroke() следует использовать fill(). Рассмотрим пример:

function CreateImage() {
	var cnvs = document.getElementById("canvas");
   var ctxt = cnvs.getContext("2d");
   ctxt.strokeStyle = "#F26700";
   ctxt.lineWidth = 6;
   ctxt.beginPath();
   ctxt.moveTo(35,30);
   ctxt.lineTo(75,20);
   ctxt.lineTo(115,30);
   ctxt.lineTo(105,110);
   ctxt.lineTo(75,120);
   ctxt.lineTo(45,110);
   ctxt.closePath();
   ctxt.stroke();
} 

Результат работы скрипта представлен на нижнем рисунке

Рисование дуг и кривых

Для рисования дуг используется метод arc(x, y, r, start, end, direction). Здесь x и y - координаты центра окружности, которой соответствует дуга, r - ее радиус, start - угол начала дуги, end - угол конца дуги, direction - логическое значение направления дуги (true - по часовой стрелке, false - против часовой стрелки)

Например, строка

 ctxt.arc(75, 130, 75, 1.25*Math.PI, 1.75 * Math.PI, false);

построит следующую дугу:

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

  ctxt.arc(75, 75, 50, 0, 2 * Math.PI, true);

И в результате получится окружность:

На холсте также есть возможность изображать кривые - квадратичные и кубические (кривые Безье). Для этого необходимо воспользоваться следующими методами:

  • quadraticCurveTo (Px, Py, x, y) - создает квадратичную кривую
  • bezierCurveTo (P1x, P1y, P2x, P2y, x, y) - создает кривую Безье

Здесь x и у - это точки в которые необходимо перейти, а координаты P - это дополнительные точки, необходимые для построения кривых. Одна для квадратичной и две для кривой Безье. Рассмотрим пример:

function CreateImage() {
  var cnvs = document.getElementById("canvas");
  var ctxt = cnvs.getContext("2d");
  ctxt.strokeStyle = "#85c200";
  ctxt.lineWidth = 6;
  ctxt.beginPath();
  ctxt.moveTo(10, 15);
  ctxt.bezierCurveTo(40, 40, 100, 20, 140, 90);
  ctxt.quadraticCurveTo(40, 150, 10, 15);
  ctxt.closePath();
  ctxt.stroke();
} 

Результат отображен на рисунке внизу:

Вставка текста

Существует два метода и несколько свойств для вывода и форматирования текста. Для вывода текста используют следующие методы:

  • strokeText('text', x, y, width) - выводит на холст текст без заливки. Здесь 'text' выводимая строка, x и y - координаты верхнего левого угла блока с текстом на холсте, width - максимальная ширина блока с текстом. Если выводимый текст получается шире, холст выводит его либо шрифтом с уменьшенной шириной символов (если данный шрифт поддерживает такое начертание), либо шрифтом меньшего размера.
  • fillText('text', x, y, width) - выводит на холст текст без контура, только заливкой. Все параметры повторяют аналогичные у метода strokeText().

Для форматирования текста есть несколько различный свойств:

  • font - свойство позволяет установить все возможные параметры выводимого шрифта. Соответствует аналогичному стилевому свойству font
  • textAlign - свойство позволяет выравнивать текст относительно блока вывода (точки, которая задается координатами x и y)
  • textBaseline - свойство позволяет задать вертикальное выравннивание текста относительно базовой линии 

Пример вывода текста:

function CreateImage() {
   var cnvs = document.getElementById("canvas");
   var ctxt = cnvs.getContext("2d");
   ctxt.strokeStyle = "black";
   ctxt.font = "bold 30pt sans-serif";
   ctxt.textAlign = "center";
   ctxt.strokeText("HTML5", 75, 70, 120);
   ctxt.fillStyle = "orange";
   ctxt.font = "italic 28pt serif";
   ctxt.textAlign = "center";
   ctxt.fillText("Canvas", 75, 100, 120);
   ctxt.stroke();
} 

Результат ниже:

Размещение на холсте внешних изображений

Кроме рисования графических элементов на холсте можно разместить уже готовое изображение в любом из стандартных форматов. Для этого необходимо создать экземпляр объекта Image. Пример использования:

function createImage()  {
   var ctx = document.getElementById('canvas').getContext('2d');
   var img = new Image(); // создание нового изображения
   img.src = 'img.jpg'; // путь к источнику для img
   img.onload = function()  {  // функция, вызываемая при загрузке img
      ctx.drawImage(img,w*200,h*160,200,160); /* вызов метода для отрисовки изображения на холсте
												  с переменными начальными координатами */
	   }
   }