При переходе к разработке картографических приложений на базе Mapbox GL JS часто возникает необходимость переноса решений из других библиотек: Leaflet, OpenLayers, Google Maps JavaScript API, Yandex Maps API, Cesium и других. Несмотря на различия в архитектуре, большинство задач остаются одинаковыми:
Mapbox GL JS реализует многие привычные возможности иначе, используя векторный рендеринг на базе WebGL и собственную модель источников данных и слоев.
Во многих картографических библиотеках существует основной объект карты.
const map = L.map('map').setView([55.751244, 37.618423], 10);
const map = new google.maps.Map(document.getElementById('map'), {
center: { lat: 55.751244, lng: 37.618423 },
zoom: 10
});
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [37.618423, 55.751244],
zoom: 10
});
Особенность Mapbox GL JS заключается в порядке координат:
[долгота, широта]
В отличие от многих библиотек, использующих формат:
[широта, долгота]
Это одна из самых распространенных ошибок при миграции проектов.
Практически все картографические библиотеки позволяют изменить центральную точку отображения.
map.panTo([55.751244, 37.618423]);
map.panTo({
lat: 55.751244,
lng: 37.618423
});
map.panTo([37.618423, 55.751244]);
Для мгновенного перемещения используется:
map.jumpTo({
center: [37.618423, 55.751244]
});
map.setZoom(12);
map.setZoom(12);
map.setZoom(12);
Метод полностью совпадает по назначению.
Также доступны дополнительные методы:
map.zoomIn();
map.zoomOut();
Во многих библиотеках существует единый метод для установки положения карты.
map.setView([55.751244, 37.618423], 12);
map.setCenter({
lat: 55.751244,
lng: 37.618423
});
map.setZoom(12);
map.flyTo({
center: [37.618423, 55.751244],
zoom: 12
});
Либо:
map.jumpTo({
center: [37.618423, 55.751244],
zoom: 12
});
Во многих API используется плавное перемещение камеры.
map.flyTo([55.751244, 37.618423], 12);
map.panTo({
lat: 55.751244,
lng: 37.618423
});
map.flyTo({
center: [37.618423, 55.751244],
zoom: 12,
speed: 1.2
});
Метод flyTo() считается основным аналогом анимированного
перехода между областями карты.
Практически каждая картографическая библиотека имеет собственный класс маркера.
L.marker([55.751244, 37.618423]).addTo(map);
new google.maps.Marker({
position: {
lat: 55.751244,
lng: 37.618423
},
map: map
});
new mapboxgl.Marker()
.setLngLat([37.618423, 55.751244])
.addTo(map);
Маркер можно дополнительно настраивать:
new mapboxgl.Marker({
color: 'red',
draggable: true
});
marker.getPosition();
marker.getLatLng();
marker.getLngLat();
Результат:
{
lng: 37.618423,
lat: 55.751244
}
Аналог Popup присутствует почти во всех библиотеках.
marker.bindPopup('Москва');
const infoWindow = new google.maps.InfoWindow({
content: 'Москва'
});
const popup = new mapboxgl.Popup()
.setHTML('<h3>Москва</h3>');
new mapboxgl.Marker()
.setLngLat([37.618423, 55.751244])
.setPopup(popup)
.addTo(map);
Большинство библиотек используют систему подписки на события.
map.on('click', function(e) {
console.log(e.latlng);
});
map.addListener('click', function(e) {
console.log(e.latLng);
});
map.on('click', function(e) {
console.log(e.lngLat);
});
Координаты доступны через объект:
e.lngLat.lng
e.lngLat.lat
map.off('click', handler);
map.off('click', handler);
Подход полностью идентичен.
Во многих библиотеках существует возможность загрузки GeoJSON напрямую.
L.geoJSON(data).addTo(map);
vectorSource.addFeatures(features);
Работа строится через источники данных.
map.addSource('cities', {
type: 'geojson',
data: data
});
После создания источника необходимо создать слой.
map.addLayer({
id: 'cities-layer',
type: 'circle',
source: 'cities'
});
Это одно из фундаментальных отличий Mapbox GL JS.
layer.addTo(map);
map.addLayer(layer);
map.addLayer({
id: 'roads',
type: 'line',
source: 'roads-source'
});
Слой всегда описывается объектом конфигурации.
map.removeLayer(layer);
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);
Подобный подход заменяет обновление объектов вручную.
map.getCenter();
map.getCenter();
map.getCenter();
Возвращается объект:
LngLat {
lng: 37.618423,
lat: 55.751244
}
map.getZoom();
map.getZoom();
Поведение практически одинаково.
map.getBounds();
map.getBounds();
map.getBounds();
Результат содержит:
const bounds = map.getBounds();
bounds.getNorth();
bounds.getSouth();
bounds.getEast();
bounds.getWest();
Аналог ограничения карты определенной территорией.
map.setMaxBounds(bounds);
map.setMaxBounds([
[30, 50],
[45, 60]
]);
Пользователь не сможет переместиться за указанные пределы.
Одна из наиболее востребованных функций.
map.fitBounds(bounds);
map.fitBounds(bounds);
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.
map.forEachFeatureAtPixel(...);
Обычно реализуется через события объектов.
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() |
Наиболее важные архитектурные отличия:
[lng, lat].Source + Layer.Именно модель «источник данных + слой + стиль» выступает главным аналогом множества функций, реализованных иначе в Leaflet, OpenLayers, Google Maps и других картографических платформах.