SVG и canvas — это технологии, которые можно использовать для рисования чего-либо на веб-страницах. Поэтому их стоит сравнить и разобраться в том, когда стоит применять SVG, а когда — canvas. Даже весьма поверхностное понимание сути этих технологий позволяет сделать вполне осознанный выбор. Собственно говоря, вот — две типичных ситуации, в одной из которых стоит предпочесть SVG, а в другой — canvas:
- Нужно нарисовать небольшую иконку? Это, безусловно, территория SVG.
- Нужно создать интерактивную браузерную игру? Тут, определённо, нужна технология canvas.
Автор статьи, перевод которой мы сегодня публикуем, говорит, что знает о том, что пока не раскрыл причины такого выбора. Но он надеется, что эти причины станут совершенно очевидными после того, как он поделится некоторыми подробностями об SVG и canvas.
SVG — векторная графика, описываемая декларативно
Если вы знаете о том, что вам нужно разместить на веб-странице векторное изображение, это значит, что вам подходит SVG. Векторные изображения обычно выглядят лучше аналогичных растровых, хранящихся, например, в JPG-файлах. Кроме того, файлы векторных изображений обычно меньше файлов растровых изображений.
В результате оказывается, что SVG очень часто используется для рисования логотипов. Код, описывающий такие изображения, можно встроить прямо в HTML. Он выглядит как набор декларативных инструкций:
<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="50" />
</svg>
Если вам нужно, чтобы изображения были бы гибкими и отзывчивыми, значит SVG — это ваш выбор.
Canvas — JavaScript-API для рисования
Для формирования canvas-изображений в HTML-коде страницы размещают элемент
<canvas>
, после чего, средствами JavaScript, «рисуют» на этом элементе. Другими словами, программист даёт браузеру команды, касающиеся того, как ему нужно что-то нарисовать (такой подход ближе к императивному, чем к декларативному). Вот как это выглядит:<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 70;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
</script>
SVG-изображения хранятся в DOM
Если вы знакомы с событиями DOM, наподобие
click
и mouseDown
, то знайте о том, что этими событиями можно пользоваться и при работе с SVG. В этом плане SVG-элемент <circle>
не особенно сильно отличается от HTML-элемента <div>
.<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="50" />
<script>
document.querySelector('circle').addEventListener('click', e => {
e.target.style.fill = "red";
});
</script>
</svg>
SVG лучше подходит для обеспечения доступности содержимого страниц
Элементу canvas вполне можно назначит его текстовую альтернативу:
<canvas aria-label="Hello ARIA World" role="img"></canvas>
То же самое можно сделать и для SVG-элемента. Но, так как SVG-изображения и их внутренние механизмы хранятся прямо в DOM, SVG обычно рассматривают как технологию, используемую в тех случаях, когда создают проекты, отличающиеся доступностью для людей с ограниченными возможностями.
Другими словами — можно создать SVG-изображение, с элементами которого смогут работать ассистивные технологии, помогающие своим пользователям ориентироваться на веб-страницах.
Текстовые данные, являющиеся частью изображений, это тоже тот случай, когда предпочтительнее использовать SVG. В SVG даже имеется специальный элемент —
<text>
. Он позволяет выводить чёткие символы текстов, его воспринимают ассистивные технологии. В случае же использования для визуализации текстов элемента canvas, такие тексты нередко выводятся некачественно, выглядят размытыми.Canvas лучше подходит для работы с изображениями на уровне отдельных пикселей
Ниже мы приведём несколько таблиц, составленных на основе сравнения SVG и canvas различными экспертами. В одном из таких сравнений, выполненном Сарой Драснер, сказано, что с помощью canvas можно заставить пиксели танцевать. Это, конечно, шутка, но, в сущности, так оно и есть.
Canvas отлично подходит для создания интерактивных изображений, содержащих множество сложных деталей, градиентных переходов цветов и прочего подобного. Именно по этой причине canvas используется при разработке гораздо большего количества браузерных игр, чем SVG. Хотя, конечно, всегда можно найти отклонения от общих тенденций. Вот, например, игра, графика которой создана средствами SVG.
SVG-игра
Обратите внимание на то, что её графическая составляющая очень проста и выглядит достаточно «векторно».
На SVG-изображения можно воздействовать с помощью CSS
Выше мы уже говорили о том, что SVG-элементы хранятся в DOM, и о том, что доступ к этим элементам можно получить из JavaScript-кода. В случае с CSS эта история повторяется:
<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="50" />
<style>
circle { fill: blue; }
</style>
</svg>
Обратите внимание на то, что в примерах блоки
<script>
и <style>
размещаются внутри блока <svg>
. Это — совершенно нормально. Но если учесть то, что SVG-элемент находится в обычном HTML-коде, то окажется, что внутренние блоки <script>
и <style>
вполне можно из него убрать. Кроме того, если нужно, можно воздействовать на SVG-элемент с помощью внешних стилей и скриптов.Вот большой материал о свойствах SVG-элементов и CSS. Самое важное здесь это то, что всё, что можно делать с элементами страниц средствами CSS, относится и к SVG. Например — это использование псевдокласса
:hover
и анимирование элементов.Вот пример анимирования элемента
<circle>
средствами CSS.<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="50" />
<style>
circle { fill: blue; animation: pulse 2s alternate infinite; }
@keyframes pulse {
100% {
r: 30;
}
}
</style>
<script>
document.querySelector('circle').addEventListener('click', e => {
e.target.style.fill = "red";
});
</script>
</svg>
Анимирование элемента SVG-изображения средствами CSS
Комбинация SVG и canvas
С технической точки зрения технологии canvas и SVG нельзя назвать взаимоисключающими. Например, SVG-изображения можно выводить в элементы
<canvas>
. При этом, как можно видеть в данном примере, SVG-изображения, выводимые в элемент <canvas>
, вполне могут оставаться весьма чёткими и качественными.Вывод SVG-изображения в элемент <canvas>
Теперь давайте рассмотрим несколько таблиц, в которых обобщены сравнения SVG и canvas, выполненные различными экспертами.
Сравнение SVG и canvas
▍Рут Джон
Вот проект, на основе которого построена следующая таблица.
Возможность |
SVG |
Canvas |
---|---|---|
Векторная графика |
+ |
— |
Растровая графика |
— | + |
Доступ в DOM |
+ |
— |
Доступность |
+ |
± |
Вывод текста |
+ |
+ |
Вывод градиентов и паттернов |
+ |
+ |
Поддержка CSS-анимации |
+ |
— |
Поддержка CSS-фильтров |
+ |
+ |
Поддержка SVG-фильтров |
+ |
+ |
Поддержка вывода файлов изображений и видеофайлов |
— | + |
Экспорт содержимого элемента |
— | + |
Управление отдельными пикселями |
— | + |
Доступ из JavaScript |
— | + |
Производительность анимации |
± |
+ |
Поддержка вычислений, выполняемых за пределами главного потока |
— | + |
▍Сара Драснер
Следующая таблица составлена на основе этого твита.
DOM/Virtual DOM |
Canvas |
|
---|---|---|
Преимущества | Отлично подходит для UI/UX-анимации. | Танцуйте, пиксели! |
Отлично подходит для вывода SVG-изображений, независимых от разрешения. | Отлично подходит для вывода 3D-графики и для других подобных вариантов использования. | |
Легко отлаживать. | Удобно управлять множеством движущихся объектов. | |
Недостатки | Изображения создаются из множества отдельных объектов. | Сложнее обеспечить доступность содержимого. |
В свете предыдущего минуса оказывается, что при анимации SVG-изображений нужно проявлять осторожность. | В стандартном виде canvas-изображения зависимы от разрешения. | |
Сложно организовать взаимодействие пользователя с отдельными элементами изображения. |
▍Ширли Ву
В основу следующей таблицы положен этот твит.
SVG |
Canvas |
|
---|---|---|
Преимущества |
Легче изучить. |
Очень высокая производительность. |
Легче организовать реакцию на воздействия пользователя. |
Легче обновлять. |
|
Легче анимировать. |
||
Недостатки |
Возможна необходимость в использовании сложных DOM-структур. |
Сложнее изучить. |
Низкая производительность при работе с большим количеством элементов. |
Сложнее обрабатывать воздействия пользователя. |
|
Для анимации объектов нужно писать собственный код. |
Многие считают, что для работы с большим количеством объектов (по словам Ширли — это когда их больше 1000) лучше подходит canvas.
SVG — это стандартный выбор. Canvas — это запасной вариант
Вот ответ на мой твит по поводу вариантов использования SVG и canvas. Автор этого ответа говорит, что выбор между SVG и canvas нужно делать так: «Используйте canvas тогда, когда не можете использовать SVG». Среди ситуаций, в которых не получается нормально пользоваться SVG, можно отметить такие, в которых нужно анимировать тысячи объектов, работать с каждым конкретным пикселем изображения, и так далее.
Итоги
В начале этого материала мы привели два типичных варианта использования SVG и canvas. Вернёмся к ним и расширим их описания с учётом того, что мы только что узнали.
- Нужно нарисовать небольшую иконку? Это, безусловно, территория SVG. Дело в том, что описание SVG-изображения хранится в DOM, в результате SVG отлично подходит для того, чтобы нарисовать что-то вроде значка на кнопке. Не стоит и говорить о том, что на SVG-изображения можно влиять средствами CSS, и, с помощью JavaScript, подключать к их элементам обработчики событий.
- Нужно создать интерактивную браузерную игру? Тут, определённо, нужна технология canvas. Браузерная игра, наверняка, будет содержать множество движущихся элементов и сложных анимаций. Элементы игрового мира будут взаимодействовать друг с другом, что означает определённые требования к производительности. Для решения таких задач отлично подходит canvas.
Надо отметить, что между этими двумя крайними вариантами есть большая промежуточная зона. Я, например, как веб-разработчик и дизайнер, считаю, что SVG удобнее с практической точки зрения. Я даже не знаю, стал бы я делать некий реальный проект с использованием canvas. Пожалуй, отчасти это так из-за того, что я недостаточно хорошо знаком с canvas. А с SVG я знаком неплохо. Я эту технологию изучал, написал о ней книгу. Как результат — я знаю об SVG достаточно для того, чтобы эта технология помогала бы мне делать то, что мне нужно.
Уважаемые читатели! В каких ситуациях вы используете SVG, а в каких — canvas?