В Leaflet векторный рендеринг через SVG используется для отображения геометрических слоёв поверх тайловой карты с помощью DOM-элементов SVG, где каждая линия, полигон или окружность преобразуется в соответствующий SVG-path. Такой подход обеспечивает высокую чёткость на любых масштабах, поскольку графика не теряет качество при масштабировании карты.
SVG renderer в Leaflet представляет собой слой абстракции над DOM,
который управляет созданием единого SVG-контейнера внутри панели карты.
Все векторные объекты группируются внутри <svg>
элемента, а конкретные геометрии представлены через
<path>.
Основные компоненты:
<svg>)<g>)translate и scaleКаждый векторный слой Leaflet преобразуется в SVG path, а обновление состояния карты (панорамирование, зум) вызывает перерасчёт трансформаций.
Leaflet поддерживает два основных рендера векторных данных: SVG и Canvas.
SVG:
Canvas:
SVG renderer выбирается по умолчанию для небольших и средних наборов данных, где важна интерактивность отдельных объектов.
В Leaflet SVG renderer создаётся через L.svg():
const map = L.map('map');
const svgRenderer = L.svg();
svgRenderer.addTo(map);
Однако чаще renderer не добавляется вручную, а используется через
опцию renderer.
Каждый векторный слой может быть привязан к конкретному renderer:
const map = L.map('map');
const svg = L.svg();
L.circle([51.5, -0.09], {
radius: 500,
renderer: svg,
color: 'red',
weight: 2
}).addTo(map);
Если renderer не указан, Leaflet автоматически выбирает SVG или Canvas в зависимости от окружения и настроек.
SVG renderer принимает набор опций, влияющих на поведение контейнера:
const svg = L.svg({
padding: 0.1,
tolerance: 3
});
Ключевые параметры:
padding
tolerance
Leaflet преобразует географические координаты в пиксельные через проекцию карты, после чего формирует SVG path.
Например, polyline:
L.polyline([
[51.5, -0.1],
[51.51, -0.12],
[51.52, -0.1]
], {
color: 'blue',
renderer: L.svg()
}).addTo(map);
Внутри это преобразуется в строку path вида:
M x1 y1 L x2 y2 L x3 y3
SVG renderer поддерживает все основные vector layers:
Линии отображаются через последовательность сегментов:
L.polyline(coords, {
weight: 4,
opacity: 0.8,
renderer: L.svg()
});
Полигоны формируются как замкнутые path:
L.polygon(coords, {
fillColor: 'green',
fillOpacity: 0.4,
renderer: L.svg()
});
Круги могут быть представлены как географические радиусы или пиксельные маркеры:
L.circle([51.5, -0.09], {
radius: 1000,
renderer: L.svg()
});
SVG renderer тесно интегрирован с FeatureGroup, позволяя
управлять наборами объектов как единым слоем:
const group = L.featureGroup([
L.circle([51.5, -0.09], { radius: 500 }),
L.polyline([[51.49, -0.08], [51.5, -0.06]])
]).addTo(map);
Все элементы группы будут находиться внутри одного SVG контейнера, сохраняя единый жизненный цикл.
SVG renderer использует path-стили Leaflet:
L.polyline(coords, {
color: '#3388ff',
weight: 5,
opacity: 1,
dashArray: '10, 5',
lineCap: 'round',
lineJoin: 'round'
});
Поддерживаемые свойства:
colorweightopacityfillColorfillOpacitydashArraylineCaplineJoinЭти параметры транслируются в SVG attributes и CSS styles.
SVG renderer не перерисовывает геометрию при каждом зуме. Вместо
этого используется трансформация группы <g>:
Это позволяет минимизировать перерасчёт path-данных, сохраняя производительность.
Каждый SVG path остаётся DOM-элементом, поэтому поддерживаются стандартные события:
const poly = L.polygon(coords, {
renderer: L.svg()
}).addTo(map);
poly.on('click', function () {
console.log('Polygon clicked');
});
События:
SVG позволяет точно определять попадание курсора в конкретный объект через hit-testing браузера.
SVG хорошо масштабируется до сотен и тысяч объектов, но имеет ограничения:
Оптимизации:
simplify() для GeoJSONFeatureGroupSVG renderer активно используется при отображении GeoJSON:
L.geoJSON(data, {
renderer: L.svg(),
style: function (feature) {
return {
color: feature.properties.color,
weight: 2
};
}
}).addTo(map);
Каждая геометрия преобразуется в SVG path, сохраняя привязку к исходным данным.
Leaflet позволяет создавать расширенные renderer на основе базового SVG:
const CustomSVG = L.SVG.extend({
_initContainer: function () {
L.SVG.prototype._initContainer.call(this);
this._container.setAttribute('class', 'custom-svg-layer');
}
});
const customRenderer = function () {
return new CustomSVG();
};
Такой подход используется для внедрения дополнительных SVG-слоёв или кастомной логики управления DOM.
В одной карте можно комбинировать разные renderer:
L.polyline(coords, { renderer: L.svg() }).addTo(map);
L.circle([51.5, -0.1], { renderer: L.canvas() }).addTo(map);
Это позволяет балансировать между качеством и производительностью в зависимости от типа данных.
SVG контейнер автоматически подстраивается под изменения viewport:
<svg>Это происходит синхронно с событиями resize и
zoom.
SVG renderer обеспечивает высокую точность hit-area, поскольку каждый path — отдельный элемент DOM. Это даёт возможность:
Анимации часто реализуются через изменение stroke-dashoffset или opacity.
SVG renderer сталкивается с системными ограничениями браузера: