Создание объектов

В библиотеке Mapbox GL JS основой всей работы выступает экземпляр карты, создаваемый через конструктор mapboxgl.Map. Именно этот объект становится контейнером для всех последующих сущностей: источников данных, слоёв, маркеров, изображений и пользовательских компонентов.

Создание карты требует минимального набора параметров: контейнера, стиля, центра и масштаба.

mapboxgl.accessToken = 'YOUR_ACCESS_TOKEN';

const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v12',
  center: [37.6173, 55.7558],
  zoom: 10
});

После инициализации формируется объектная модель карты, в которую встраиваются все последующие элементы. Архитектура Mapbox GL JS основана на декларативном описании слоёв и источников данных, где каждый объект имеет собственный жизненный цикл и обновляется независимо.


Создание источников данных (Sources)

Источники данных представляют собой фундамент визуализации. Они определяют, откуда поступает информация для отображения на карте. Основной формат — GeoJSON, хотя поддерживаются и тайловые источники.

Добавление источника выполняется через метод addSource.

map.on('load', () => {
  map.addSource('points-source', {
    type: 'geojson',
    data: {
      type: 'FeatureCollection',
      features: [
        {
          type: 'Feature',
          geometry: {
            type: 'Point',
            coordinates: [37.6173, 55.7558]
          },
          properties: {
            title: 'Центральная точка'
          }
        }
      ]
    }
  });
});

Каждый источник представляет собой независимый объект внутри состояния карты. При изменении данных через setData происходит автоматическое обновление всех связанных слоёв.

const source = map.getSource('points-source');

source.setData({
  type: 'FeatureCollection',
  features: []
});

Ключевой принцип заключается в разделении данных и визуализации: источник не содержит информации о внешнем виде, он отвечает только за структуру и геометрию.


Создание слоёв (Layers)

Слои отвечают за отображение данных, поступающих из источников. Каждый слой привязан к конкретному source и определяет способ визуализации: точки, линии, полигоны, текст или растровые данные.

map.addLayer({
  id: 'points-layer',
  type: 'circle',
  source: 'points-source',
  paint: {
    'circle-radius': 8,
    'circle-color': '#ff0000'
  }
});

Тип слоя определяет набор доступных свойств:

  • circle — отображение точек
  • line — линии и маршруты
  • fill — полигоны
  • symbol — текст и иконки
  • heatmap — тепловые карты

Слои формируют стек отрисовки. Порядок добавления влияет на визуальную иерархию. Управление порядком осуществляется через beforeId.

map.addLayer(layerConfig, 'waterway-label');

Создание маркеров

Маркер представляет собой DOM-объект, закреплённый за координатами карты. В отличие от слоёв, маркеры не используют WebGL-рендеринг и могут содержать произвольную HTML-разметку.

const marker = new mapboxgl.Marker()
  .setLngLat([37.6173, 55.7558])
  .addTo(map);

Поддерживается создание пользовательских маркеров через DOM-элемент:

const el = document.createElement('div');
el.className = 'custom-marker';

const marker = new mapboxgl.Marker(el)
  .setLngLat([37.6, 55.7])
  .addTo(map);

Маркер может быть связан с событиями и динамически обновляться:

marker.setLngLat([37.62, 55.76]);

При увеличении количества маркеров снижается производительность, так как каждый объект существует как отдельный DOM-узел.


Создание всплывающих окон (Popup)

Popup является привязанным к координате объектом интерфейса, отображающим информацию поверх карты.

const popup = new mapboxgl.Popup()
  .setLngLat([37.6173, 55.7558])
  .setHTML('<h3>Объект</h3><p>Описание точки</p>')
  .addTo(map);

Popup может быть привязан к маркеру:

marker.setPopup(popup);

Основные параметры управления поведением:

  • closeButton
  • closeOnClick
  • offset

Popup создаёт отдельный слой DOM, который управляется независимо от WebGL-сцены.


Создание пользовательских изображений

Для symbol-слоёв часто требуется регистрация изображений в стиле карты. Изображения добавляются в стиль через addImage.

map.on('load', () => {
  map.loadImage('icon.png', (error, image) => {
    if (error) throw error;

    map.addImage('custom-icon', image);

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

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


Создание GeoJSON объектов

GeoJSON выступает стандартным способом описания геометрии. В рамках Mapbox GL JS он используется для точек, линий и полигонов.

Точка

{
  type: 'Feature',
  geometry: {
    type: 'Point',
    coordinates: [37.6173, 55.7558]
  }
}

Линия

{
  type: 'Feature',
  geometry: {
    type: 'LineString',
    coordinates: [
      [37.61, 55.75],
      [37.62, 55.76]
    ]
  }
}

Полигон

{
  type: 'Feature',
  geometry: {
    type: 'Polygon',
    coordinates: [[
      [37.61, 55.75],
      [37.62, 55.75],
      [37.62, 55.76],
      [37.61, 55.76],
      [37.61, 55.75]
    ]]
  }
}

Структура GeoJSON определяет не только геометрию, но и свойства, используемые в стилизации:

properties: {
  name: 'Объект',
  category: 'important'
}

Создание динамических источников и обновление данных

Динамическое поведение достигается через обновление источников в реальном времени. Это применяется при отображении движущихся объектов, трекинга и аналитических систем.

setInterval(() => {
  const source = map.getSource('points-source');

  source.setData({
    type: 'FeatureCollection',
    features: [
      {
        type: 'Feature',
        geometry: {
          type: 'Point',
          coordinates: [
            37.6173 + Math.random() * 0.01,
            55.7558 + Math.random() * 0.01
          ]
        }
      }
    ]
  });
}, 1000);

Обновление данных автоматически вызывает перерасчёт всех зависимых слоёв без необходимости ручного перерендера.


Создание 3D объектов и extrusion слоёв

Mapbox GL JS поддерживает трёхмерную визуализацию через fill-extrusion слой.

map.addLayer({
  id: 'buildings',
  source: 'composite',
  'source-layer': 'building',
  type: 'fill-extrusion',
  paint: {
    'fill-extrusion-color': '#aaa',
    'fill-extrusion-height': ['get', 'height'],
    'fill-extrusion-base': ['get', 'min_height'],
    'fill-extrusion-opacity': 0.6
  }
});

Высота объектов извлекается из атрибутов данных, что позволяет строить реалистичные 3D сцены городской застройки.


Создание кастомных контролов

Контролы расширяют функциональность карты и создаются как объекты с методами onAdd и onRemove.

class CustomControl {
  onAdd(map) {
    this._map = map;
    this._container = document.createElement('div');
    this._container.className = 'custom-control';
    this._container.innerText = 'Control';
    return this._container;
  }

  onRemove() {
    this._container.parentNode.removeChild(this._container);
    this._map = undefined;
  }
}

map.addControl(new CustomControl());

Контрол становится частью интерфейса карты и управляется через жизненный цикл Mapbox.


Создание анимаций объектов

Анимация реализуется через обновление координат или параметров слоя в цикле requestAnimationFrame.

function animate() {
  const source = map.getSource('points-source');

  const time = Date.now() * 0.001;

  source.setData({
    type: 'FeatureCollection',
    features: [
      {
        type: 'Feature',
        geometry: {
          type: 'Point',
          coordinates: [
            37.6173 + Math.sin(time) * 0.01,
            55.7558 + Math.cos(time) * 0.01
          ]
        }
      }
    ]
  });

  requestAnimationFrame(animate);
}

animate();

Подобный подход используется для визуализации движения транспорта, потоков данных и интерактивных симуляций.


Создание событийной модели объектов

Каждый объект карты может быть связан с событиями: кликом, наведением, перемещением.

map.on('click', 'points-layer', (e) => {
  const feature = e.features[0];

  new mapboxgl.Popup()
    .setLngLat(feature.geometry.coordinates)
    .setHTML(feature.properties.title)
    .addTo(map);
});

События работают на уровне слоёв, что позволяет обрабатывать большое количество объектов без привязки к DOM.


Создание составных визуальных структур

Сложные визуализации формируются через комбинацию источников, слоёв и интерфейсных объектов. Например, кластеризация точек:

map.addSource('clusters', {
  type: 'geojson',
  data: geojsonData,
  cluster: true,
  clusterMaxZoom: 14,
  clusterRadius: 50
});

Отображение кластеров требует нескольких слоёв: для самих кластеров, их числовых значений и отдельных точек.


Создание временных и условных объектов

Слои могут зависеть от условий данных через выражения:

paint: {
  'circle-color': [
    'case',
    ['==', ['get', 'category'], 'important'],
    '#ff0000',
    '#0000ff'
  ]
}

Так формируются динамические стили, реагирующие на свойства объектов.


Организация структуры объектов внутри стиля карты

Стиль карты в Mapbox GL JS представляет собой JSON-структуру, содержащую:

  • sources
  • layers
  • sprite
  • glyphs

Каждый элемент стиля является объектом с собственной конфигурацией и идентификатором. Управление стилем позволяет централизованно изменять поведение всей карты без изменения логики приложения.


Управление жизненным циклом объектов

Объекты карты создаются, изменяются и удаляются через API экземпляра карты.

Удаление слоя:

map.removeLayer('points-layer');

Удаление источника:

map.removeSource('points-source');

Удаление изображения:

map.removeImage('custom-icon');

Корректное управление жизненным циклом предотвращает утечки памяти и снижает нагрузку на WebGL контекст.