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

Автор: Мациевский Николай 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 style="left:0;top:0;width:100;height:50"
	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 xmlns="http://www.w3.org/2000/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

Пример простого изображения при помощи Canvas, источник developer.mozilla.org

Дополнительно Canvas позволяет определить практически любые действия пользователя над описываемыми объектами (перемещение и нажатия мыши) и загрузить в область объекты MathML и SVG. Как мы видим, на данный момент это полноценная платформа для произвольной анимации прямо в том же браузере, который предназначен для просмотра отдельных HTML-страниц. Можно с уверенностью предсказать, что через пару лет обычные Flash-банеры будут вытеснены их более интерактивными и более «поддерживаемыми» коллегами на основе Canvas (и, например, VML для семейства браузеров IE).

Подробнее со спецификацией Canvas можно ознакомиться, например, на странице WHATWG.

Примеры использования

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

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

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

Изображение чайника при помощи Canvas

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

Typeface.js

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

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

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

Применение Canvas для стилизации шрифтов

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

Prosessing.js

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

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

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

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

Raphaёl

Если предыдущий пример был посвящен использованию Canvas больше в развлекательных целях, то библиотека Raphael.js преследует сугубо практические цели. С ее помощью можно удобно и красиво представлять различные объемы данных во всем привычном формате графиков.

Использование этой библиотеки предельно просто: обычно нужно объявить необходимые данные и задать один из множества доступных представлений (или создать свое собственное). Более подробно можно ознакомиться на сайте самой библиотеки http://raphaeljs.com/.

Пример использования Raphael.js для отображения данных

Пример использования Raphael.js для отображения данных, источник raphaeljs.com

Проблемы быстродействия

На данный момент Canvas при решении большинства задач справляется с ними быстрее, чем SVG. Достаточно давно был разработан пример использования Canvas для ряда задач Google Maps. В нем зафиксирован прирост скорости в 200-500% (для всех браузеров, которые поддерживают Canvas).

Быстродействие Canvas

Быстродействие Canvas, источник www.ernestdelgado.com

В результате другого тестирования Canvas также демонстрирует значительное преимущество перед SVG, но менее широкий набор возможностей.

Возможности и быстродействие Canvas

Возможности и быстродействие Canvas, источник prototype-graphic.xilinus.com

Также можно привести еще один тест скорости отображения объектов в Canvas и SVG. Здесь SVG снова проигрывает.

Сравнение быстродействия Canvas и SVG

Сравнение быстродействия Canvas и SVG, источник ntertwingly.net

Для уточнения вопросов производительности можно обратиться к исследованию, установившему закономерность между производительностью SVG, Canvas и параметрами изображения. В результате оказывается вполне очевидным, что при увеличении числа объектов (для SVG — векторных) производительность SVG падает сильно (почти экспоненциально), а Canvas — остается на стабильном уровне. Здесь стоит отметить, что размер активной области при этом не изменяется.

Производительность Canvas и SVG при увеличении числа объектов

Производительность Canvas и SVG при увеличении числа объектов, источник www.borismus.com

Однако если мы начнем увеличивать область построения (размеры объектов), то тут векторный формат показывает себя во всей красе: производительность практически не меняется. Производительность Canvas падает (как и следовало ожидать) квадратичным образом от числа объектов (площадь активной области увеличивается квадратично).

Производительность Canvas и SVG при увеличении размера объектов

Производительность Canvas и SVG при увеличении размера объектов, источник www.borismus.com

Из этого можно сделать простой вывод: если вы собираетесь использовать точечную (пиксельную) графику, то лучше Canvas для этой цели ничего не подходит. При работе с большими (по площади) векторными объектами лучше использовать SVG. Также будет необходимо дублировать всю функциональность через VML для IE 8 и ниже.

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

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