Прежде чем начать разговор о текущем положении вещей с поддержкой векторной и скалярной графики в браузерах, стоит немного углубиться в историю.
В 1998 году компания Microsoft при поддержке других крупных производителей предложила W3C свой стандарт отображения векторной информации — VML (англ. Vector Markup Language — векторный язык разметки). Он был основан на текущем формате представления документов в вебе — HTML — и расширял его до некоторого «векторного» языка. Компания Microsoft активно продвигала и продвигает данный формат и включает его во все версии IE, начиная с 5.0. В рамках стандарта он окончательно закреплен в качестве части спецификации Open Office XML (ISO 29500:2008 и ECMA-376) в 2008 году.
В этом же 1998 году Adobe, IBM, Netscape и Sun вносят в W3C предложение о рассмотрение своего стандарта в противовес Microsoft — PGML (англ. Precision Graphics Markup Language — точный графический язык разметки). Не желая делать ни один стандарт проприетарным, W3C создает свою рабочую группу, которая на основе имеющихся предложений в 1999 году создает набросок еще одного стандарта — SVG (англ. Scalable Vector Graphics — масштабируемая векторная графика). Данный стандарт (хотя до сих пор закрепленный только в форме рекомендации, последняя версия 1.1 от 2003 года) находит гораздо большую поддержку у производителей браузеров и на данный момент включен практически везде (кроме, естественно, IE).
Сейчас большинство JavaScript-библиотек, которые предлагают работу с векторной графикой, включают поддержку SVG для всех браузеров и поддержку VML для IE. В качестве характерного примера можно привести Яндекс.Карты или Google Maps. Оба формата (SVG и VML) обладают практически одинаковыми возможностями, например, ниже приведен код на VML для отображения синего овала:
<html xmlns:v="VML"> <style type="text/css">v\:*{behavior:url(#default#VML);position:absolute}</style> <body> <v:oval fillcolor="blue" stroked="f"/> </body> </html>
Этот же код на SVG:
<?xml version="1.0"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="100" height="50"> <ellipse cx="50" cy="25" rx="50" ry="25" fill="blue" stroke="none" /> </svg>
Спецификация Canvas (как отдельной области на странице, внутри которой можно отображать графические объекты) в 2005 году изначально была предложена со стороны Apple для поддержки некоторых приложений внутри движка WebKit (на данный момент его используют браузеры Safari и Chrome). Рабочая группа W3C включила Canvas в Web Applications 1.0, который вошел в готовящийся стандарт HTML 5.0.
Сейчас встроенная поддержка Canvas реализована в том или ином виде во всех современных браузерах. В IE версии 8 и ниже она эмулируется при помощи отдельного VML-документа.
В качестве основного отличия от VML и SVG стоит назвать принципиальную невозможность описать какой-либо элемент в Canvas, используя строго HTML и CSS: все действия производятся только при помощи JavaScript. Также стоит упомянуть, что SVG оперирует с отдельными векторными объектами и их взаимосвязями, тогда как Canvas предлагает интерфейс к пиксельной области на странице, не предлагая устанавливать дополнительных связей (все они находятся в зоне ответственности JavaScript).
Canvas предлагает достаточно мощное API для действий над двумерными графическими объектами. В том числе, это вывод и преобразование текста (в том числе загрузка произвольного шрифта), отображение двумерных объектов (прямоугольников, треугольников, кругов и многоугольников), работа с векторной графикой (задается как объект пути), преобразование над фигурами (прозрачность, перемещение, поворот и даже матрица преобразования), работа с отдельными линиями и тенями. Также возможна работа с изображениями в попиксельном формате (что позволяет сделать практически полноценный Photoshop внутри отдельного браузера) и коррекция цвета.
Давайте рассмотрим следующий простой пример использования Canvas:
<html> <head> <script type="application/x-javascript"> function draw() { var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(200,0,0)"; ctx.fillRect (10, 10, 55, 50); ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; ctx.fillRect (30, 30, 55, 50); } window.onload = draw; </script> </head> <body> <canvas id="canvas" width="300" height="300"></canvas> </body> </html>
В результате его исполнения мы получим следующее изображение
Пример простого изображения при помощи Canvas, источник developer.mozilla.org
Дополнительно Canvas позволяет определить практически любые действия пользователя над описываемыми объектами (перемещение и нажатия мыши) и загрузить в область объекты MathML и SVG. Как мы видим, на данный момент это полноценная платформа для произвольной анимации прямо в том же браузере, который предназначен для просмотра отдельных HTML-страниц. Можно с уверенностью предсказать, что через пару лет обычные Flash-банеры будут вытеснены их более интерактивными и более «поддерживаемыми» коллегами на основе Canvas (и, например, VML для семейства браузеров IE).
Подробнее со спецификацией Canvas можно ознакомиться, например, на странице WHATWG.
Примеров использования Canvas довольно много, и они частично охватывают уже известные области 2D-графики.
С помощью Canvas можно изображать 2D-проекции трехмерных объектов. В силу того что все преобразования выполняются на пиксельном уровне, достаточно просто создать необходимые интерфейсы для изометрических проекций трехмерных объектов. Видимо, достаточно скоро на основе Canvas появятся полноценные 3D-экскурсии в браузерах или онлайн-игры «от первого лица».
Изображение чайника при помощи Canvas, источник www.nihilogic.dk
В качестве следующего применения стоит упомянуть библиотеку typeface.js и созданный на ее основе метод отображения произвольных шрифтов на сайте (ранее для этой цели активно использовался Flash). Единственный минус данного подхода (на фоне повышенного быстродействия в связи с естественной поддержкой Canvas и простоты использования) является большой размер файла самих шрифтов.
Для применения библиотеки typeface.js необходимо перевести требуемый шрифт в некоторый объект, описываемый с помощью соответствующих конструкций на JavaScript, затем этот объект будет использоваться для представления произвольного текста на сайте (если быть точным, то в качестве объекта выступают отдельные символы шрифта). Размер файла шрифта в текстовом формате сильно варьируется от количества включенных в него символов и может составлять от 50 до 500 Кб (в неархивированном виде).
Для больших порталов (где размер страницы составляет 500-1000 Кб) данный подход вполне приемлем (если «стилизованных» заголовков будет не так много, чтобы лишний раз не нагружать браузер преобразованиями страницы). Для небольших сайтов загрузка нескольких десятков Кб JavaScript-кода для стилизации 10 Кб HTML- и CSS-кода выглядит не очень уместной.
Применение Canvas для стилизации шрифтов, источник typeface.neocracy.org
Processing — язык программирования, созданный Casey Reas и Benjamin Fry в академических целях и направленный на кроссплатформенную обработку двумерных графических объектов. Он может быть реализован на любой аппаратной платформе путем преобразования исходных конструкций в платформо-зависимые инструкции.
Хорошим примером использования Canvas является реализация Processing для JavaScript (автор реализации — John Resig, он же автор jQuery) — библиотека Processing.js. Она предполагает полную совместимость инструкций данного языка с преобразованиями объекта Canvas. На данный момент доступно несколько проектов, использующих Processing.js, в частности, несколько игр в браузерах, например, «Защита башен».
Использование processing.js для игры «Защита башен», источник willarson.com
Если предыдущий пример был посвящен использованию Canvas больше в развлекательных целях, то библиотека Raphael.js преследует сугубо практические цели. С ее помощью можно удобно и красиво представлять различные объемы данных во всем привычном формате графиков.
Использование этой библиотеки предельно просто: обычно нужно объявить необходимые данные и задать один из множества доступных представлений (или создать свое собственное). Более подробно можно ознакомиться на сайте самой библиотеки http://raphaeljs.com/.
Пример использования Raphael.js для отображения данных, источник raphaeljs.com
На данный момент Canvas при решении большинства задач справляется с ними быстрее, чем SVG. Достаточно давно был разработан пример использования Canvas для ряда задач Google Maps. В нем зафиксирован прирост скорости в 200-500% (для всех браузеров, которые поддерживают Canvas).
Быстродействие Canvas, источник www.ernestdelgado.com
В результате другого тестирования Canvas также демонстрирует значительное преимущество перед SVG, но менее широкий набор возможностей.
Возможности и быстродействие Canvas, источник prototype-graphic.xilinus.com
Также можно привести еще один тест скорости отображения объектов в Canvas и SVG. Здесь SVG снова проигрывает.
Сравнение быстродействия Canvas и SVG, источник ntertwingly.net
Для уточнения вопросов производительности можно обратиться к исследованию, установившему закономерность между производительностью SVG, Canvas и параметрами изображения. В результате оказывается вполне очевидным, что при увеличении числа объектов (для SVG — векторных) производительность SVG падает сильно (почти экспоненциально), а Canvas — остается на стабильном уровне. Здесь стоит отметить, что размер активной области при этом не изменяется.
Производительность Canvas и SVG при увеличении числа объектов, источник www.borismus.com
Однако если мы начнем увеличивать область построения (размеры объектов), то тут векторный формат показывает себя во всей красе: производительность практически не меняется. Производительность Canvas падает (как и следовало ожидать) квадратичным образом от числа объектов (площадь активной области увеличивается квадратично).
Производительность Canvas и SVG при увеличении размера объектов, источник www.borismus.com
Из этого можно сделать простой вывод: если вы собираетесь использовать точечную (пиксельную) графику, то лучше Canvas для этой цели ничего не подходит. При работе с большими (по площади) векторными объектами лучше использовать SVG. Также будет необходимо дублировать всю функциональность через VML для IE 8 и ниже.