Векторные карты в Mapbox GL JS используют систему стилей, где большинство графических элементов представлено через иконки и изображения. Эти изображения объединяются в единый набор ресурсов — sprite, который обеспечивает быстрый доступ к графике при рендеринге карты. Sprite представляет собой комбинацию растрового файла (PNG/WebP) и JSON-описания координат каждого изображения внутри этого файла.
Ключевая особенность sprite заключается в том, что он загружается один раз при инициализации стиля, после чего все иконки берутся из локального кэша браузера без дополнительных сетевых запросов.
В стиле Mapbox GL JS sprite задаётся через свойства:
sprite: базовый URL без расширения
автоматически подгружаются файлы:
sprite.png — изображение-атласsprite.json — описание координатПример:
{
"version": 8,
"sprite": "mapbox://sprites/username/styleid"
}
или при локальном использовании:
{
"version": 8,
"sprite": "https://example.com/sprites/sprite"
}
В этом случае библиотека запрашивает:
https://example.com/sprites/sprite.pnghttps://example.com/sprites/sprite.jsonJSON содержит метаданные:
{
"icon-name": {
"x": 0,
"y": 0,
"width": 32,
"height": 32,
"pixelRatio": 1
}
}
Каждый ключ соответствует имени изображения, используемого в стиле
через icon-image.
Sprite сам по себе не отображается на карте. Он используется через свойства слоёв, например:
{
"id": "points",
"type": "symbol",
"source": "places",
"layout": {
"icon-image": "icon-name"
}
}
Значение icon-image должно совпадать с ключом в sprite
JSON.
Mapbox GL JS позволяет добавлять изображения в sprite во время
выполнения с помощью метода addImage.
map.on('load', () => {
map.loadImage('https://example.com/icon.png', (error, image) => {
if (error) throw error;
map.addImage('custom-icon', image);
});
});
После добавления изображение становится доступным как часть sprite и может использоваться в стилях:
{
"id": "markers",
"type": "symbol",
"source": "points",
"layout": {
"icon-image": "custom-icon"
}
}
Метод addImage поддерживает дополнительные параметры,
влияющие на отображение:
map.addImage('custom-icon', image, {
pixelRatio: 2,
sdf: true
});
pixelRatio — масштабирование для Retina-дисплеевsdf — включение Signed Distance Field рендеринга,
позволяющего менять цвет иконки через icon-colorSDF особенно полезен для однотонных иконок:
"paint": {
"icon-color": "#ff0000"
}
Изображения нельзя использовать до полной загрузки стиля. Обычно используется событие:
map.on('load', () => {
// безопасное добавление изображений
});
При работе с динамическими стилями важно учитывать, что при смене
стиля (setStyle) sprite очищается, и изображения нужно
добавлять заново через style.load.
map.on('style.load', () => {
map.addImage('custom-icon', image);
});
Перед добавлением можно проверить наличие изображения в sprite:
if (!map.hasImage('custom-icon')) {
map.addImage('custom-icon', image);
}
Это предотвращает ошибки повторного добавления.
Для управления памятью и обновления ресурсов используется:
map.removeImage('custom-icon');
Удалённое изображение перестаёт быть доступным в слоях, которые его используют.
Прямой метод обновления отсутствует, но можно заменить изображение:
map.removeImage('custom-icon');
map.addImage('custom-icon', newImage);
Это позволяет динамически изменять иконки в зависимости от состояния данных.
Загрузка изображений выполняется через loadImage,
который поддерживает CORS:
map.loadImage('https://example.com/icon.png', callback);
При использовании внешних доменов важно учитывать:
Использование sprite значительно ускоряет рендеринг:
При большом количестве иконок предпочтительно использовать единый sprite atlas вместо множества отдельных файлов.
Sprite можно генерировать автоматически из набора изображений. Инструменты обычно объединяют:
Результат должен соответствовать формату Mapbox:
{
"icon-name": {
"x": 64,
"y": 32,
"width": 32,
"height": 32,
"pixelRatio": 1
}
}
Каждое изображение размещается в общем атласе без перекрытия.
При создании собственного стиля через Style Specification sprite можно полностью заменить:
{
"sprite": "https://cdn.example.com/my-sprite"
}
Это позволяет:
Sprite в Mapbox GL JS часто используется в сценариях:
При этом ключевым становится баланс между количеством уникальных иконок и эффективностью их хранения в sprite.