Статьи Архив статей

Автор: Мациевский Николай aka sunnybear
Опубликована: 11 июля 2009

Canvas: один шаг назад, два шага вперед

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

Предыстория

В 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

Спецификация 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-графики.

2D-проекции 3D-объектов

С помощью Canvas можно изображать 2D-проекции трехмерных объектов. В силу того что все преобразования выполняются на пиксельном уровне, достаточно просто создать необходимые интерфейсы для изометрических проекций трехмерных объектов. Видимо, достаточно скоро на основе Canvas появятся полноценные 3D-экскурсии в браузерах или онлайн-игры «от первого лица».

Изображение чайника при помощи Canvas, источник www.nihilogic.dk

Typeface.js

В качестве следующего применения стоит упомянуть библиотеку typeface.js и созданный на ее основе метод отображения произвольных шрифтов на сайте (ранее для этой цели активно использовался Flash). Единственный минус данного подхода (на фоне повышенного быстродействия в связи с естественной поддержкой Canvas и простоты использования) является большой размер файла самих шрифтов.

Для применения библиотеки typeface.js необходимо перевести требуемый шрифт в некоторый объект, описываемый с помощью соответствующих конструкций на JavaScript, затем этот объект будет использоваться для представления произвольного текста на сайте (если быть точным, то в качестве объекта выступают отдельные символы шрифта). Размер файла шрифта в текстовом формате сильно варьируется от количества включенных в него символов и может составлять от 50 до 500 Кб (в неархивированном виде).

Для больших порталов (где размер страницы составляет 500-1000 Кб) данный подход вполне приемлем (если «стилизованных» заголовков будет не так много, чтобы лишний раз не нагружать браузер преобразованиями страницы). Для небольших сайтов загрузка нескольких десятков Кб JavaScript-кода для стилизации 10 Кб HTML- и CSS-кода выглядит не очень уместной.

Применение Canvas для стилизации шрифтов, источник typeface.neocracy.org

Prosessing.js

Processing — язык программирования, созданный Casey Reas и Benjamin Fry в академических целях и направленный на кроссплатформенную обработку двумерных графических объектов. Он может быть реализован на любой аппаратной платформе путем преобразования исходных конструкций в платформо-зависимые инструкции.

Хорошим примером использования Canvas является реализация Processing для JavaScript (автор реализации — John Resig, он же автор jQuery) — библиотека Processing.js. Она предполагает полную совместимость инструкций данного языка с преобразованиями объекта Canvas. На данный момент доступно несколько проектов, использующих Processing.js, в частности, несколько игр в браузерах, например, «Защита башен».

Использование processing.js для игры «Защита башен», источник willarson.com

Raphaёl

Если предыдущий пример был посвящен использованию 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 и ниже.

Читать дальше

Все комментарии (habrahabr.ru)