Аналоги функций

При переходе к разработке картографических приложений на базе Mapbox GL JS часто возникает необходимость переноса решений из других библиотек: Leaflet, OpenLayers, Google Maps JavaScript API, Yandex Maps API, Cesium и других. Несмотря на различия в архитектуре, большинство задач остаются одинаковыми:

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

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


Создание карты

Во многих картографических библиотеках существует основной объект карты.

Leaflet

const map = L.map('map').setView([55.751244, 37.618423], 10);

Google Maps

const map = new google.maps.Map(document.getElementById('map'), {
    center: { lat: 55.751244, lng: 37.618423 },
    zoom: 10
});

Mapbox GL JS

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

Особенность Mapbox GL JS заключается в порядке координат:

[долгота, широта]

В отличие от многих библиотек, использующих формат:

[широта, долгота]

Это одна из самых распространенных ошибок при миграции проектов.


Центрирование карты

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

Leaflet

map.panTo([55.751244, 37.618423]);

Google Maps

map.panTo({
    lat: 55.751244,
    lng: 37.618423
});

Mapbox GL JS

map.panTo([37.618423, 55.751244]);

Для мгновенного перемещения используется:

map.jumpTo({
    center: [37.618423, 55.751244]
});

Изменение масштаба

Leaflet

map.setZoom(12);

Google Maps

map.setZoom(12);

Mapbox GL JS

map.setZoom(12);

Метод полностью совпадает по назначению.

Также доступны дополнительные методы:

map.zoomIn();
map.zoomOut();

Изменение центра и масштаба одновременно

Во многих библиотеках существует единый метод для установки положения карты.

Leaflet

map.setView([55.751244, 37.618423], 12);

Google Maps

map.setCenter({
    lat: 55.751244,
    lng: 37.618423
});

map.setZoom(12);

Mapbox GL JS

map.flyTo({
    center: [37.618423, 55.751244],
    zoom: 12
});

Либо:

map.jumpTo({
    center: [37.618423, 55.751244],
    zoom: 12
});

Анимация перемещения

Во многих API используется плавное перемещение камеры.

Leaflet

map.flyTo([55.751244, 37.618423], 12);

Google Maps

map.panTo({
    lat: 55.751244,
    lng: 37.618423
});

Mapbox GL JS

map.flyTo({
    center: [37.618423, 55.751244],
    zoom: 12,
    speed: 1.2
});

Метод flyTo() считается основным аналогом анимированного перехода между областями карты.


Добавление маркеров

Практически каждая картографическая библиотека имеет собственный класс маркера.

Leaflet

L.marker([55.751244, 37.618423]).addTo(map);

Google Maps

new google.maps.Marker({
    position: {
        lat: 55.751244,
        lng: 37.618423
    },
    map: map
});

Mapbox GL JS

new mapboxgl.Marker()
    .setLngLat([37.618423, 55.751244])
    .addTo(map);

Маркер можно дополнительно настраивать:

new mapboxgl.Marker({
    color: 'red',
    draggable: true
});

Получение координат маркера

Google Maps

marker.getPosition();

Leaflet

marker.getLatLng();

Mapbox GL JS

marker.getLngLat();

Результат:

{
    lng: 37.618423,
    lat: 55.751244
}

Всплывающие окна

Аналог Popup присутствует почти во всех библиотеках.

Leaflet

marker.bindPopup('Москва');

Google Maps

const infoWindow = new google.maps.InfoWindow({
    content: 'Москва'
});

Mapbox GL JS

const popup = new mapboxgl.Popup()
    .setHTML('<h3>Москва</h3>');

new mapboxgl.Marker()
    .setLngLat([37.618423, 55.751244])
    .setPopup(popup)
    .addTo(map);

Обработка событий карты

Большинство библиотек используют систему подписки на события.

Leaflet

map.on('click', function(e) {
    console.log(e.latlng);
});

Google Maps

map.addListener('click', function(e) {
    console.log(e.latLng);
});

Mapbox GL JS

map.on('click', function(e) {
    console.log(e.lngLat);
});

Координаты доступны через объект:

e.lngLat.lng
e.lngLat.lat

Удаление обработчиков событий

Leaflet

map.off('click', handler);

Mapbox GL JS

map.off('click', handler);

Подход полностью идентичен.


Добавление GeoJSON

Во многих библиотеках существует возможность загрузки GeoJSON напрямую.

Leaflet

L.geoJSON(data).addTo(map);

OpenLayers

vectorSource.addFeatures(features);

Mapbox GL JS

Работа строится через источники данных.

map.addSource('cities', {
    type: 'geojson',
    data: data
});

После создания источника необходимо создать слой.

map.addLayer({
    id: 'cities-layer',
    type: 'circle',
    source: 'cities'
});

Это одно из фундаментальных отличий Mapbox GL JS.


Добавление слоя

Leaflet

layer.addTo(map);

OpenLayers

map.addLayer(layer);

Mapbox GL JS

map.addLayer({
    id: 'roads',
    type: 'line',
    source: 'roads-source'
});

Слой всегда описывается объектом конфигурации.


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

Leaflet

map.removeLayer(layer);

Mapbox GL JS

map.removeLayer('roads');

Удаление происходит по идентификатору слоя.


Управление источниками данных

В большинстве библиотек источник данных скрыт внутри слоя.

В Mapbox GL JS источник является самостоятельным объектом.

Добавление:

map.addSource('buildings', {
    type: 'geojson',
    data: geojson
});

Получение:

const source = map.getSource('buildings');

Удаление:

map.removeSource('buildings');

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


Изменение данных слоя

Аналог обновления коллекции объектов реализуется через метод setData().

const source = map.getSource('cities');

source.setData(newGeoJson);

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


Получение текущего центра карты

Leaflet

map.getCenter();

Google Maps

map.getCenter();

Mapbox GL JS

map.getCenter();

Возвращается объект:

LngLat {
    lng: 37.618423,
    lat: 55.751244
}

Получение текущего масштаба

Leaflet

map.getZoom();

Mapbox GL JS

map.getZoom();

Поведение практически одинаково.


Получение границ видимой области

Leaflet

map.getBounds();

Google Maps

map.getBounds();

Mapbox GL JS

map.getBounds();

Результат содержит:

const bounds = map.getBounds();

bounds.getNorth();
bounds.getSouth();
bounds.getEast();
bounds.getWest();

Ограничение области просмотра

Аналог ограничения карты определенной территорией.

Leaflet

map.setMaxBounds(bounds);

Mapbox GL JS

map.setMaxBounds([
    [30, 50],
    [45, 60]
]);

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


Подгонка карты под границы объектов

Одна из наиболее востребованных функций.

Leaflet

map.fitBounds(bounds);

Google Maps

map.fitBounds(bounds);

Mapbox GL JS

map.fitBounds([
    [30, 50],
    [45, 60]
]);

С дополнительными настройками:

map.fitBounds(
    [
        [30, 50],
        [45, 60]
    ],
    {
        padding: 50,
        duration: 1000
    }
);

Управление вращением карты

В большинстве старых библиотек вращение отсутствует либо ограничено.

Mapbox GL JS предоставляет полноценную поддержку.

Установка угла:

map.setBearing(45);

Получение:

map.getBearing();

Анимированное изменение:

map.easeTo({
    bearing: 90
});

Управление наклоном карты

Поддержка трехмерного наклона является одной из особенностей Mapbox GL JS.

Установка наклона:

map.setPitch(60);

Получение:

map.getPitch();

Анимация:

map.easeTo({
    pitch: 70
});

Подобный функционал отсутствует в большинстве классических 2D-библиотек.


Управление стилями

В Leaflet визуальное оформление часто зависит от тайлового слоя.

tileLayer.setUrl(url);

В Mapbox GL JS используется единый стиль карты.

Изменение стиля:

map.setStyle(
    'mapbox://styles/mapbox/dark-v11'
);

Получение текущего стиля:

map.getStyle();

Контролы интерфейса

Аналоги элементов управления существуют практически в каждом API.

Масштабирование

map.addControl(
    new mapboxgl.NavigationControl()
);

Геолокация

map.addControl(
    new mapboxgl.GeolocateControl()
);

Полноэкранный режим

map.addControl(
    new mapboxgl.FullscreenControl()
);

Масштабная линейка

map.addControl(
    new mapboxgl.ScaleControl()
);

Получение объектов под курсором

Аналог hit testing или feature picking.

OpenLayers

map.forEachFeatureAtPixel(...);

Google Maps

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

Mapbox GL JS

const features = map.queryRenderedFeatures(
    e.point
);

Для конкретного слоя:

const features =
    map.queryRenderedFeatures(e.point, {
        layers: ['cities']
    });

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


Аналоги основных функций

Задача Leaflet Google Maps Mapbox GL JS
Создать карту L.map() new Map() new mapboxgl.Map()
Изменить центр panTo() panTo() panTo()
Изменить масштаб setZoom() setZoom() setZoom()
Получить масштаб getZoom() getZoom() getZoom()
Получить центр getCenter() getCenter() getCenter()
Добавить маркер L.marker() Marker mapboxgl.Marker()
Popup bindPopup() InfoWindow Popup
Подписаться на событие on() addListener() on()
Удалить обработчик off() removeListener() off()
Подогнать границы fitBounds() fitBounds() fitBounds()
Добавить GeoJSON geoJSON() Data Layer addSource() + addLayer()
Изменить стиль TileLayer MapType setStyle()
Получить объекты layer events hit test queryRenderedFeatures()

Особенности замены функций при миграции на Mapbox GL JS

Наиболее важные архитектурные отличия:

  1. Координаты задаются в формате [lng, lat].
  2. Вместо объектов слоев часто используются пары Source + Layer.
  3. Векторный рендеринг основан на WebGL.
  4. Стиль карты управляется единым JSON-описанием.
  5. Поддерживаются наклон и вращение камеры.
  6. Работа с объектами осуществляется через механизм Feature и GeoJSON.
  7. Значительная часть визуализации выполняется средствами стилей, а не программного кода.

Именно модель «источник данных + слой + стиль» выступает главным аналогом множества функций, реализованных иначе в Leaflet, OpenLayers, Google Maps и других картографических платформах.