Работа с изображениями в Mapbox GL JS основана на двух основных механизмах: использование спрайтов стиля и динамическая загрузка внешних ресурсов во время выполнения. Внешние изображения применяются для кастомных маркеров, паттернов заливки полигонов, иконок символов и динамически изменяемых элементов интерфейса карты.
В основе загрузки лежит метод map.loadImage, который
асинхронно получает изображение по URL и преобразует его в формат,
пригодный для использования внутри WebGL-контекста.
Загрузка внешнего изображения выполняется через API карты:
map.loadImage(
'https://example.com/icon.png',
(error, image) => {
if (error) throw error;
map.addImage('custom-icon', image);
}
);
ImageData/HTMLImageElement;addImage.После загрузки изображение должно быть добавлено в стиль:
map.addImage('custom-marker', image, {
pixelRatio: 2
});
addImageПосле регистрации изображение становится доступным в слоях типа
symbol.
map.addLayer({
id: 'points',
type: 'symbol',
source: 'points-source',
layout: {
'icon-image': 'custom-marker',
'icon-size': 1
}
});
addImage;При работе с изменяющимися данными изображения часто загружаются в момент появления слоя или данных.
function addRemoteIcon(url, name) {
map.loadImage(url, (error, image) => {
if (error) return;
if (!map.hasImage(name)) {
map.addImage(name, image);
}
});
}
if (map.hasImage('custom-marker')) {
// изображение уже зарегистрировано
}
Внешние изображения могут применяться как паттерны для полигонов:
map.addLayer({
id: 'water-pattern',
type: 'fill',
source: 'water',
paint: {
'fill-pattern': 'water-texture'
}
});
Такие изображения должны быть предварительно добавлены через
addImage.
Изображение может быть использовано только после завершения загрузки стиля:
map.on('load', () => {
map.loadImage('/icon.png', (error, image) => {
if (error) return;
map.addImage('icon', image);
});
});
Попытка добавить изображение до события load приводит к
ошибкам, связанным с отсутствием стиля.
При загрузке внешних изображений применяется политика CORS.
Access-Control-Allow-Origin;Изображение можно заменить без пересоздания слоя:
map.updateImage('custom-marker', newImage);
Если прямое обновление недоступно, используется последовательность:
if (map.hasImage('custom-marker')) {
map.removeImage('custom-marker');
}
map.addImage('custom-marker', image);
Signed Distance Field позволяет перекрашивать иконки через стили:
map.addImage('icon-sdf', image, { sdf: true });
icon-color;Загруженные изображения хранятся в стиле карты:
addImage с тем же ID игнорируется;hasImage предотвращает дублирование;map.removeImage('custom-marker');
Mapbox Mapbox предоставляет встроенную систему спрайтов, однако внешние изображения используются в случаях:
pixelRatio вместо физического увеличения
размеров;Часто изображения применяются совместно с geojson
источниками:
map.addSource('points', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [30.5, 50.5]
}
}
]
}
});
map.addLayer({
id: 'points-layer',
type: 'symbol',
source: 'points',
layout: {
'icon-image': 'custom-marker',
'icon-allow-overlap': true
}
});
map.loadImage(url, (error, image) => {
if (error) {
console.error('Ошибка загрузки изображения');
return;
}
map.addImage('icon', image);
});
Изображение может быть создано динамически:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = 50;
canvas.height = 50;
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 50, 50);
map.addImage('canvas-icon', ctx.getImageData(0, 0, 50, 50));