Маркеры в SVG — это специальные графические элементы, которые автоматически привязываются к концам, началу или промежуточным точкам линий, кривых и полилиний. Наиболее распространённое применение — стрелки, точки, индикаторы направлений.
В библиотеке SVG.js работа с маркерами упрощается за счёт абстракций,
позволяющих не взаимодействовать напрямую с <marker>
и <defs>, а использовать декларативный API.
Ключевая особенность маркеров — их позиционирование относительно геометрии элемента и системы координат.
Маркер в SVG определяется отдельным контейнером с собственной системой координат. При привязке к элементу учитываются:
В SVG.js базовый пример создания маркера:
const draw = SVG().addTo('#app').size(400, 400)
const marker = draw.marker(10, 10, function(add) {
add.path('M0,0 L10,5 L0,10 Z').fill('#000')
})
const line = draw.line(50, 50, 200, 200)
line.marker('end', marker)
SVG поддерживает три типа позиционирования маркеров:
В SVG.js это задаётся методом
.marker(position, marker):
line.marker('start', marker)
line.marker('mid', marker)
line.marker('end', marker)
Особенности:
mid применяется ко всем внутренним вершинамpath маркеры размещаются в узлах сегментовКаждый маркер имеет параметры:
refXrefYОни определяют, какая точка внутри маркера будет совпадать с точкой привязки на линии.
В SVG.js:
const marker = draw.marker(10, 10, function(add) {
add.circle(10).fill('red')
}).ref(5, 5)
Ключевые моменты:
(0,0) — левый верх маркераrefX/refY смещает маркер относительно
линииПример центрированной стрелки:
marker.ref(10, 5)
По умолчанию маркер может иметь фиксированную ориентацию, но чаще используется автоматическое вращение вдоль направления линии.
SVG.js поддерживает:
marker.orient('auto')
или
marker.orient('auto-start-reverse')
Различия:
auto — направление по касательной линииauto-start-reverse — автоматически переворачивает
маркер в началеЭто особенно важно для стрелок:
line.marker('start', marker)
line.marker('end', marker)
marker.orient('auto-start-reverse')
Размер маркера может зависеть от толщины линии или быть фиксированным.
Параметр:
markerUnitsВ SVG.js:
marker.units('strokeWidth')
или
marker.units('userSpaceOnUse')
Различия:
Пример:
line.stroke({ width: 5 })
marker.units('strokeWidth')
Даже при правильной точке привязки часто требуется дополнительное смещение.
Это достигается комбинацией:
refX / refYПример тонкой настройки стрелки:
const marker = draw.marker(20, 20, function(add) {
add.path('M0,0 L20,10 L0,20 Z').fill('#000')
}).ref(20, 10)
Здесь:
(20,10)Для path с кривыми (C, Q,
A) маркеры размещаются:
SVG.js не требует ручного расчёта касательных — браузер автоматически определяет угол.
Пример:
const path = draw.path('M50,200 C150,50 250,350 350,200')
path.marker('end', marker)
Особенности:
Для polyline:
const polyline = draw.polyline('50,150 150,50 250,150 350,50')
polyline.marker('mid', marker)
Поведение:
Для polygon:
polylineПри использовании одного маркера для начала и конца линии может возникнуть проблема направления.
Решения:
marker.orient('auto-start-reverse')
line.marker('start', startMarker)
line.marker('end', endMarker)
Внутренние элементы маркера можно трансформировать:
const marker = draw.marker(20, 20, function(add) {
add.path('M0,0 L20,10 L0,20 Z')
.fill('black')
.transform({ scale: 0.8, translateX: 2 })
})
Это позволяет:
Маркеры используют собственный viewBox, влияющий на
масштабирование и позиционирование.
В SVG.js:
marker.viewbox(0, 0, 20, 20)
Связь параметров:
viewBox определяет внутреннюю систему координатwidth/height — внешний размерrefX/refY — позиция привязки внутри
viewBoxЧасто используемый паттерн:
const arrow = draw.marker(10, 10, function(add) {
add.path('M0,0 L10,5 L0,10 Z').fill('#000')
})
.ref(10, 5)
.orient('auto')
.units('strokeWidth')
const line = draw.line(50, 50, 300, 50)
line.stroke({ width: 2 })
line.marker('end', arrow)
Ключевые параметры:
ref(10,5) — острие стрелкиorient('auto') — направлениеunits('strokeWidth') — масштабированиеПричины:
refX/refYviewBoxРешение:
Причины:
orient('auto')Причины:
userSpaceOnUseviewBox и размеровДля mid:
line.plot(100, 100, 300, 300)
Маркеры автоматически пересчитываются.
line.animate().plot(50, 200, 300, 50)
Маркеры следуют за геометрией.
Один маркер можно использовать для множества элементов:
line1.marker('end', arrow)
line2.marker('end', arrow)
Это снижает нагрузку и упрощает управление стилями.
Если линия трансформируется:
line.rotate(45)
Если SVG вложен в группы (<g>):
const group = draw.group()
group.add(line)
Позиционирование маркера определяется комбинацией:
start/mid/end)refX/refYorientmarkerUnitsviewBoxПонимание взаимодействия этих параметров позволяет точно контролировать визуальное поведение маркеров в любых сценариях.