- PVSM.RU - https://www.pvsm.ru -
SVG и canvas — это технологии, которые можно использовать для рисования чего-либо на веб-страницах. Поэтому их стоит сравнить и разобраться в том, когда стоит применять SVG, а когда — canvas. Даже весьма поверхностное понимание сути этих технологий позволяет сделать вполне осознанный выбор. Собственно говоря, вот — две типичных ситуации, в одной из которых стоит предпочесть SVG, а в другой — canvas:
Автор статьи, перевод которой мы сегодня публикуем, говорит, что знает о том, что пока не раскрыл причины такого выбора. Но он надеется, что эти причины станут совершенно очевидными после того, как он поделится некоторыми подробностями об SVG и canvas.
Если вы знаете о том, что вам нужно разместить на веб-странице векторное изображение, это значит, что вам подходит SVG. Векторные изображения обычно выглядят лучше аналогичных растровых, хранящихся, например, в JPG-файлах. Кроме того, файлы векторных изображений обычно меньше файлов растровых изображений.
В результате оказывается, что SVG очень часто используется для рисования логотипов [2]. Код, описывающий такие изображения, можно встроить прямо в HTML. Он выглядит как набор декларативных инструкций:
<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="50" />
</svg>
Если вам нужно, чтобы изображения были бы гибкими и отзывчивыми, значит SVG — это ваш выбор.
Для формирования 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>
Если вы знакомы с событиями 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>
Элементу canvas вполне можно назначит его текстовую альтернативу:
<canvas aria-label="Hello ARIA World" role="img"></canvas>
То же самое можно сделать и для SVG-элемента. Но, так как SVG-изображения и их внутренние механизмы хранятся прямо в DOM, SVG обычно рассматривают как технологию, используемую в тех случаях, когда создают проекты, отличающиеся доступностью для людей с ограниченными возможностями.
Другими словами — можно создать SVG-изображение, с элементами которого смогут работать ассистивные технологии, помогающие своим пользователям ориентироваться на веб-страницах.
Текстовые данные, являющиеся частью изображений, это тоже тот случай, когда предпочтительнее использовать SVG. В SVG даже имеется специальный элемент — <text>. Он позволяет выводить чёткие символы текстов, его воспринимают ассистивные технологии [3]. В случае же использования для визуализации текстов элемента canvas, такие тексты нередко выводятся некачественно [4], выглядят размытыми.
Ниже мы приведём несколько таблиц, составленных на основе сравнения SVG и canvas различными экспертами. В одном из таких сравнений, выполненном Сарой Драснер, сказано, что с помощью canvas можно заставить пиксели танцевать. Это, конечно, шутка, но, в сущности, так оно и есть.
Canvas отлично подходит для создания интерактивных изображений, содержащих множество сложных деталей, градиентных переходов цветов и прочего подобного. Именно по этой причине canvas используется при разработке гораздо большего количества браузерных игр, чем SVG. Хотя, конечно, всегда можно найти отклонения от общих тенденций. Вот [5], например, игра, графика которой создана средствами SVG.

SVG-игра
Обратите внимание на то, что её графическая составляющая очень проста и выглядит достаточно «векторно».
Выше мы уже говорили о том, что 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-элемент с помощью внешних стилей и скриптов.
Вот [6] большой материал о свойствах SVG-элементов и CSS. Самое важное здесь это то, что всё, что можно делать с элементами страниц средствами CSS, относится и к SVG. Например — это использование псевдокласса :hover и анимирование элементов.
Вот [7] пример анимирования элемента <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
С технической точки зрения технологии canvas и SVG нельзя назвать взаимоисключающими. Например, SVG-изображения можно выводить в элементы <canvas>. При этом, как можно видеть в данном [8] примере, SVG-изображения, выводимые в элемент <canvas>, вполне могут оставаться весьма чёткими и качественными.

Вывод SVG-изображения в элемент <canvas>
Теперь давайте рассмотрим несколько таблиц, в которых обобщены сравнения SVG и canvas, выполненные различными экспертами.
Вот [9] проект, на основе которого построена следующая таблица.
| Возможность | SVG | Canvas |
|---|---|---|
| Векторная графика | + | — |
| Растровая графика | — | + |
| Доступ в DOM | + | — |
| Доступность | + | ± |
| Вывод текста | + | + |
| Вывод градиентов и паттернов | + | + |
| Поддержка CSS-анимации | + | — |
| Поддержка CSS-фильтров | + | + |
| Поддержка SVG-фильтров | + | + |
| Поддержка вывода файлов изображений и видеофайлов | — | + |
| Экспорт содержимого элемента | — | + |
| Управление отдельными пикселями | — | + |
| Доступ из JavaScript | — | + |
| Производительность анимации | ± | + |
| Поддержка вычислений, выполняемых за пределами главного потока | — | + |
Следующая таблица составлена на основе этого [10] твита.
| DOM/Virtual DOM | Canvas | |
|---|---|---|
| Преимущества | Отлично подходит для UI/UX-анимации. | Танцуйте, пиксели! |
| Отлично подходит для вывода SVG-изображений, независимых от разрешения. | Отлично подходит для вывода 3D-графики и для других подобных вариантов использования. | |
| Легко отлаживать. | Удобно управлять множеством движущихся объектов. | |
| Недостатки | Изображения создаются из множества отдельных объектов. | Сложнее обеспечить доступность содержимого. |
| В свете предыдущего минуса оказывается, что при анимации SVG-изображений нужно проявлять осторожность. | В стандартном виде canvas-изображения зависимы от разрешения. | |
| Сложно организовать взаимодействие пользователя с отдельными элементами изображения. |
В основу следующей таблицы положен этот [11] твит.
| SVG | Canvas | |
|---|---|---|
| Преимущества | Легче изучить. | Очень высокая производительность. |
| Легче организовать реакцию на воздействия пользователя. | Легче обновлять. | |
| Легче анимировать. | ||
| Недостатки | Возможна необходимость в использовании сложных DOM-структур. | Сложнее изучить. |
| Низкая производительность при работе с большим количеством элементов. | Сложнее обрабатывать воздействия пользователя. | |
| Для анимации объектов нужно писать собственный код. |
Многие считают, что для работы с большим количеством объектов (по словам Ширли — это когда их больше 1000) лучше подходит canvas.
Вот [12] ответ на мой твит по поводу вариантов использования SVG и canvas. Автор этого ответа говорит, что выбор между SVG и canvas нужно делать так: «Используйте canvas тогда, когда не можете использовать SVG». Среди ситуаций, в которых не получается нормально пользоваться SVG, можно отметить такие, в которых нужно анимировать тысячи объектов, работать с каждым конкретным пикселем изображения, и так далее.
В начале этого материала мы привели два типичных варианта использования SVG и canvas. Вернёмся к ним и расширим их описания с учётом того, что мы только что узнали.
Надо отметить, что между этими двумя крайними вариантами есть большая промежуточная зона. Я, например, как веб-разработчик и дизайнер, считаю, что SVG удобнее с практической точки зрения. Я даже не знаю, стал бы я делать некий реальный проект с использованием canvas. Пожалуй, отчасти это так из-за того, что я недостаточно хорошо знаком с canvas. А с SVG я знаком неплохо. Я эту технологию изучал, написал о ней книгу [13]. Как результат — я знаю об SVG достаточно для того, чтобы эта технология помогала бы мне делать то, что мне нужно.
Уважаемые читатели! В каких ситуациях вы используете SVG, а в каких — canvas?

Автор: ru_vds
Источник [15]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/razrabotka/337180
Ссылки в тексте:
[1] Image: https://habr.com/ru/company/ruvds/blog/476292/
[2] логотипов: http://responsivelogos.co.uk/
[3] ассистивные технологии: https://css-tricks.com/svg-text-typographic-designs/
[4] некачественно: https://twitter.com/_hmig/status/1179540290941718534
[5] Вот: https://play.esviji.com/
[6] Вот: https://css-tricks.com/svg-properties-and-css/
[7] Вот: https://codepen.io/chriscoyier/pen/ExxbpBE
[8] данном: https://codepen.io/osublake/pen/WzbKLQ
[9] Вот: https://codepen.io/Rumyra/pen/qBBWryJ
[10] этого: https://twitter.com/sarah_edo/status/1179542296653631488
[11] этот: https://twitter.com/sxywu/status/1179517055093104641
[12] Вот: https://twitter.com/bdc/status/1179509488803434496
[13] книгу: https://abookapart.com/products/practical-svg
[14] Image: https://ruvds.com/ru-rub/#order
[15] Источник: https://habr.com/ru/post/476292/?utm_source=habrahabr&utm_medium=rss&utm_campaign=476292
Нажмите здесь для печати.