Символы в SVG представляют собой механизм повторного использования графических элементов без дублирования кода. Они определяются один раз и могут многократно вставляться в разные части документа с помощью специальных ссылок. Это существенно снижает размер SVG, упрощает поддержку и повышает производительность.
В библиотеке SVG.js работа с символами организована через объектную модель, позволяющую создавать, редактировать и использовать символы в декларативном и удобном стиле.
Символ создаётся с помощью метода symbol(). Он формирует
контейнер <symbol>, внутри которого можно размещать
любые SVG-элементы:
const draw = SVG().addTo('#canvas').size(600, 400)
const icon = draw.symbol()
icon.circle(50).fill('#f06')
icon.rect(80, 30).move(10, 60).fill('#0af')
Ключевые особенности:
<symbol> не отображается напрямую на сцене<use>Для отображения символа применяется метод use(), который
создаёт элемент <use> — ссылку на ранее объявленный
символ:
draw.use(icon).move(100, 100)
draw.use(icon).move(200, 100).scale(0.5)
Особенности:
use() создаёт независимый экземплярmove, scale,
rotate) применяются к экземпляру, а не к оригиналуСимволы позволяют избежать дублирования:
for (let i = 0; i < 5; i++) {
draw.use(icon).move(i * 100, 200)
}
Преимущества:
Символы могут иметь собственную систему координат через
viewbox():
icon.viewbox(0, 0, 100, 100)
Это позволяет:
Символ — полноценный контейнер, его можно изменять после создания:
icon.clear()
icon.rect(100, 100).fill('#333')
icon.text('SVG').move(10, 40).fill('#fff')
Все экземпляры автоматически отразят изменения.
Иногда требуется создать новый символ на основе существующего:
const icon2 = icon.clone()
icon2.findOne('circle').fill('#0f0')
Отличия:
clone() создаёт независимую копиюСимвол может содержать другие символы:
const base = draw.symbol()
base.circle(40).fill('#ccc')
const complex = draw.symbol()
complex.use(base).move(0, 0)
complex.use(base).move(50, 0)
Это позволяет строить композиции:
Символы поддерживают стандартные SVG-атрибуты:
icon.attr({
id: 'mySymbol',
preserveAspectRatio: 'xMidYMid meet'
})
Полезные атрибуты:
viewBox — область координатpreserveAspectRatio — поведение масштабированияid — идентификатор для ссылокПомимо объектного API, символ можно использовать через строковый идентификатор:
draw.use('#mySymbol').move(300, 100)
Это удобно при:
Каждый экземпляр можно стилизовать независимо:
draw.use(icon)
.move(100, 100)
.fill('#ff0')
draw.use(icon)
.move(200, 100)
.opacity(0.5)
Важно:
<use>, но могут
переопределять стили внутри символаfill
может вести себя по-разному в зависимости от структуры)<use><use>Экземпляры символов поддерживают обработчики событий:
draw.use(icon)
.move(100, 100)
.click(() => {
console.log('clicked')
})
Однако:
<use>, а не на
оригинальных элементахАнимация может применяться как к символу, так и к экземплярам:
draw.use(icon)
.move(100, 100)
.animate(1000)
.move(300, 100)
icon.findOne('circle')
.animate(1000)
.fill('#00f')
Все экземпляры отразят изменение, если анимация применяется к содержимому символа.
Символы часто используются для создания SVG-спрайтов:
const sprite = draw.defs()
const iconA = sprite.symbol()
iconA.circle(20).fill('red')
const iconB = sprite.symbol()
iconB.rect(40, 40).fill('blue')
Преимущества:
<defs>Хотя SVG.js автоматически управляет размещением символов, логически
они находятся внутри <defs> — специального контейнера
для невидимых элементов.
const defs = draw.defs()
const symbol = defs.symbol()
Иконки интерфейса:
Графические паттерны:
Игры и визуализация:
Использование символов:
Особенно эффективно при:
| Характеристика | symbol | group (<g>) |
|---|---|---|
| Отображение | нет | да |
| Переиспользование | да | нет (копирование) |
| Оптимизация | высокая | средняя |
| Управление | централизованное | локальное |
Символы хорошо сочетаются с:
mask)clipPath)gradient)filter)Пример:
const gradient = draw.gradient('linear', add => {
add.stop(0, '#f06')
add.stop(1, '#0af')
})
icon.rect(100, 100).fill(gradient)
1. Попытка отобразить symbol напрямую
draw.add(icon) // не работает
2. Изменение экземпляра вместо символа
draw.use(icon).findOne('circle') // не даст доступа к содержимому
3. Игнорирование viewBox
Приводит к неправильному масштабированию.
defsidviewBox для всех символовДинамическое создание символов:
function createIcon(color) {
const s = draw.symbol()
s.circle(50).fill(color)
return s
}
Параметризация через data-атрибуты:
const use = draw.use(icon)
use.data('type', 'primary')
Комбинирование с шаблонами:
<use>Элемент <use>:
href или xlink:hrefЭто объясняет:
Символы и <use> поддерживаются всеми современными
браузерами. Однако:
xlink:hrefSVG.js сглаживает часть этих различий.
Можно хранить ссылки на экземпляры:
const instances = []
for (let i = 0; i < 10; i++) {
instances.push(draw.use(icon).move(i * 50, 100))
}
Позволяет:
Символы логически близки к компонентам:
Это делает их удобными для: