В SVG-документе блок <defs> служит для хранения
определений графических элементов, которые не отображаются напрямую, но
могут быть переиспользованы в других частях сцены. В контексте
библиотеки SVG.js это ключевой механизм оптимизации и организации кода,
позволяющий:
Все элементы, помещённые в <defs>, становятся
доступными через ссылки (url(#id)), либо через методы
библиотеки.
defs() в
SVG.jsSVG.js предоставляет удобный API для взаимодействия с
<defs> через метод defs():
const draw = SVG().addTo('#app').size(600, 400)
const defs = draw.defs()
Объект defs — это контейнер, в который добавляются
переиспользуемые элементы.
symbol)Символы позволяют группировать графику и затем использовать её многократно:
const symbol = draw.symbol()
symbol.rect(50, 50).fill('red')
symbol.circle(50).move(25, 25).fill('blue')
draw.use(symbol).move(100, 100)
draw.use(symbol).move(200, 100)
Особенности:
use()use() и повторное использованиеМетод use() создаёт копию элемента из
<defs>:
const rect = defs.rect(100, 100).fill('green')
draw.use(rect).move(50, 50)
draw.use(rect).move(200, 50)
Преимущества:
SVG.js упрощает создание градиентов, которые автоматически помещаются
в <defs>.
const gradient = draw.gradient('linear', function(add) {
add.stop(0, '#ff0000')
add.stop(1, '#0000ff')
})
draw.rect(200, 100).fill(gradient)
const radial = draw.gradient('radial', function(add) {
add.stop(0, '#ffffff')
add.stop(1, '#000000')
})
draw.circle(150).fill(radial)
Особенности:
<defs>Паттерны позволяют создавать повторяющиеся текстуры:
const pattern = draw.pattern(20, 20, function(add) {
add.rect(10, 10).fill('#ccc')
add.rect(10, 10).move(10, 10).fill('#ccc')
})
draw.rect(200, 200).fill(pattern)
Характеристики:
fillМаски управляют прозрачностью элементов:
const mask = draw.mask()
mask.rect(200, 200).fill('#fff')
mask.circle(100).move(50, 50).fill('#000')
draw.rect(200, 200).fill('blue').maskWith(mask)
Принцип работы:
ClipPath ограничивает область отображения:
const clip = draw.clip()
clip.circle(100).move(50, 50)
draw.rect(200, 200).fill('orange').clipWith(clip)
Отличие от маски:
Фильтры позволяют применять визуальные эффекты:
const filter = draw.defs().element('filter').id('blur')
filter.element('feGaussianBlur')
.attr({ stdDeviation: 5 })
draw.rect(100, 100)
.fill('red')
.attr('filter', 'url(#blur)')
Популярные эффекты:
Каждый элемент в <defs> должен иметь уникальный
id:
const grad = draw.gradient('linear', add => {
add.stop(0, '#000')
add.stop(1, '#fff')
}).id('myGradient')
Использование:
draw.rect(100, 100).fill('url(#myGradient)')
SVG.js автоматически генерирует id, но их можно задавать вручную для контроля.
<defs>При работе с большим количеством элементов важно:
Пример:
const defs = draw.defs()
const gradients = defs.group().id('gradients')
const masks = defs.group().id('masks')
Элементы в <defs> можно изменять и удалять:
gradient.update(function(add) {
add.stop(0, '#00ff00')
add.stop(1, '#0000ff')
})
gradient.remove()
Изменения автоматически отражаются во всех связанных элементах.
Использование <defs> напрямую влияет на
эффективность:
Особенно важно при:
Элементы из <defs> можно анимировать:
const symbol = draw.symbol()
symbol.circle(50).fill('red')
const instance = draw.use(symbol)
instance.animate(1000).move(200, 200)
При этом:
SVG.js допускает вложенные структуры:
const symbol = draw.symbol()
const gradient = draw.gradient('linear', add => {
add.stop(0, '#f00')
add.stop(1, '#0f0')
})
symbol.rect(100, 100).fill(gradient)
draw.use(symbol)
Это позволяет создавать сложные, многослойные компоненты.
symbolpatterngradient<defs>SVG.js абстрагирует сложность нативного SVG, но сохраняет гибкость,
позволяя при необходимости работать на низком уровне через
.attr() и .element().
1. Отсутствие уникальных id Приводит к конфликтам и некорректному отображению.
2. Попытка напрямую отобразить элемент из
<defs> Такие элементы не рендерятся без
use().
3. Неправильное использование масок и clipPath Путаница между прозрачностью и обрезкой.
4. Избыточное создание градиентов Лучше переиспользовать один экземпляр.
Через <defs> удобно реализуется динамическое
обновление:
const gradient = draw.gradient('linear', add => {
add.stop(0, '#000')
add.stop(1, '#fff')
})
setTimeout(() => {
gradient.update(add => {
add.stop(0, '#ff0000')
add.stop(1, '#00ff00')
})
}, 1000)
Все элементы с этим градиентом изменятся автоматически.
SVG.js позволяет получить доступ к нативным узлам:
const node = gradient.node
console.log(node.tagName) // linearGradient
Это важно для:
Многие плагины SVG.js используют <defs>:
Это делает <defs> центральным механизмом
расширяемости.
<defs>В сложных приложениях <defs> становится:
Грамотное использование позволяет строить модульные, переиспользуемые графические системы.