Метод addImage

Метод addImage используется для добавления растрового изображения в стиль карты, где оно становится доступным как ресурс для символических слоёв (symbol layer) через свойство icon-image. Это один из ключевых механизмов кастомизации маркеров, пиктограмм и любых графических элементов, отображаемых поверх географических данных.


Назначение и область применения

addImage расширяет текущий стиль карты, регистрируя изображение под уникальным идентификатором. После добавления изображение может быть использовано в любых слоях, поддерживающих иконки, без необходимости обращения к внешним URL или спрайтам.

Основные сценарии использования:

  • кастомные маркеры объектов на карте
  • динамическая подгрузка иконок пользователей или точек интереса
  • отображение SVG/PNG пиктограмм в слоях symbol
  • создание наборов UI-иконок прямо в runtime
  • использование SDF-иконок для цветовой кастомизации через стиль слоя

Сигнатура метода

map.addImage(id, image, options?)

Параметры

id Тип: string Уникальный идентификатор изображения в рамках стиля. Используется в icon-image.


image Тип: HTMLImageElement | ImageData | ImageBitmap | Object

Допустимые формы:

  • HTMLImageElement — загруженный <img>
  • ImageBitmap — оптимизированный бинарный формат
  • ImageData — сырые пиксели
  • объект { width, height, data } — массив RGBA

options (необязательный)

{
  pixelRatio?: number,
  sdf?: boolean
}
  • pixelRatio — коэффициент масштабирования изображения
  • sdf — включает режим Signed Distance Field для стилизуемых иконок

Добавление изображения из HTMLImageElement

Наиболее распространённый сценарий — загрузка изображения и регистрация его в стиле карты.

map.on('load', () => {
  const img = new Image();
  img.onl oad = () => {
    map.addImage('custom-marker', img);
  };
  img.src = '/images/marker.png';
});

После регистрации изображение становится доступным:

map.addLayer({
  id: 'points',
  type: 'symbol',
  source: 'points-source',
  layout: {
    'icon-image': 'custom-marker',
    'icon-size': 1
  }
});

Использование ImageData

При генерации изображения динамически (например, через canvas):

const canvas = document.createElement('canvas');
canvas.width = 64;
canvas.height = 64;

const ctx = canvas.getContext('2d');
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 64, 64);

const imageData = ctx.getImageData(0, 0, 64, 64);

map.addImage('generated-square', imageData);

Такой подход применяется для:

  • генерации маркеров на лету
  • визуализации числовых данных
  • создания кастомных индикаторов состояния

Добавление ImageBitmap

ImageBitmap обеспечивает более эффективный рендеринг по сравнению с HTMLImageElement.

const img = new Image();
img.src = '/icons/poi.png';

img.onl oad = async () => {
  const bitmap = await createImageBitmap(img);
  map.addImage('poi-bitmap', bitmap);
};

Использование ImageBitmap снижает нагрузку на главный поток и ускоряет отрисовку больших наборов иконок.


Параметр pixelRatio

Позволяет контролировать плотность пикселей для экранов с высоким DPI.

map.addImage('hd-icon', img, {
  pixelRatio: 2
});

Практическое значение:

  • 1 — стандартная плотность
  • 2 — Retina-дисплеи
  • 2 — высокоплотные экраны

Неверная настройка приводит к размытию или чрезмерному масштабированию.


Режим SDF (Signed Distance Field)

SDF превращает изображение в математически масштабируемую форму, позволяющую изменять цвет и прозрачность через стиль слоя.

map.addImage('sdf-icon', img, {
  sdf: true
});

Использование в слое:

map.addLayer({
  id: 'sdf-layer',
  type: 'symbol',
  source: 'points',
  layout: {
    'icon-image': 'sdf-icon',
    'icon-size': 1
  },
  paint: {
    'icon-color': '#ff0000',
    'icon-halo-color': '#000000',
    'icon-halo-width': 2
  }
});

Особенности SDF:

  • изменение цвета без пересоздания изображения
  • масштабирование без потери качества
  • подходит для монохромных иконок

Перезапись и удаление изображений

Если изображение с таким id уже существует, его необходимо удалить перед повторным добавлением.

if (map.hasImage('custom-marker')) {
  map.removeImage('custom-marker');
}

map.addImage('custom-marker', img);

Это важно при:

  • обновлении иконок в реальном времени
  • смене темы интерфейса
  • динамической локализации ресурсов

Проверка наличия изображения

map.hasImage('custom-marker');

Возвращает true или false, позволяя безопасно управлять ресурсами.


Связь с символическими слоями

addImage не отображает изображение напрямую. Оно работает только как ресурс для слоёв типа symbol.

layout: {
  'icon-image': 'image-id'
}

Дополнительные свойства слоя:

  • icon-size
  • icon-rotate
  • icon-offset
  • icon-anchor
  • icon-opacity

Загрузка изображений из внешних источников

Mapbox GL JS поддерживает асинхронную загрузку изображений:

map.loadImage('/icons/airport.png', (error, image) => {
  if (error) throw error;
  map.addImage('airport', image);
});

Такой подход часто используется при интеграции с API или CDN.


Производительность и ограничения

При работе с addImage важно учитывать:

  • изображения хранятся в памяти WebGL контекста
  • большое количество уникальных иконок увеличивает потребление GPU-памяти
  • рекомендуется переиспользование идентификаторов
  • предпочтительнее использовать атласы или SDF для массовых объектов

Оптимизационные подходы:

  • группировка одинаковых иконок под одним id
  • использование SDF вместо растровых вариаций цветов
  • кеширование ImageBitmap
  • предварительная загрузка изображений до создания слоёв

Динамическая генерация иконок

addImage часто используется вместе с canvas для создания контекстных маркеров.

Пример: числовой бейдж

function createBadge(number) {
  const canvas = document.createElement('canvas');
  canvas.width = 64;
  canvas.height = 64;

  const ctx = canvas.getContext('2d');

  ctx.fillStyle = '#1978c8';
  ctx.beginPath();
  ctx.arc(32, 32, 30, 0, Math.PI * 2);
  ctx.fill();

  ctx.fillStyle = '#fff';
  ctx.font = 'bold 24px sans-serif';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.fillText(number, 32, 32);

  return ctx.getImageData(0, 0, 64, 64);
}

map.addImage('badge-5', createBadge(5));

Использование в системах слоёв

В сложных приложениях изображения, добавленные через addImage, используются как часть архитектуры слоёв:

  • слой кластеров → разные иконки состояний
  • слой транспортных узлов → типы объектов
  • слой аналитики → визуальные маркеры категорий

Поведение при смене стиля карты

При смене стиля (setStyle) изображения, добавленные через addImage, теряются, поскольку стиль перезагружается. Для восстановления используется событие:

map.on('styledata', () => {
  map.addImage('custom-marker', img);
});

Это критично для:

  • переключения светлой/тёмной темы
  • смены базовых стилей Mapbox
  • динамических конфигураций карты