В архитектуре Mapbox GL JS центральное понятие — камера
карты, определяющая, какой участок мира отображается в текущий
момент. Камера описывается набором параметров: center,
zoom, bearing, pitch. Среди них
center задаёт географическую точку, которая проецируется в
центр canvas.
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [69.2401, 53.2145],
zoom: 9
});
Значение center — это не геометрический центр объектов,
а точка фокуса камеры, вокруг которой строится
визуализация сцены.
map.setCenter([69.2401, 53.2145]);
const currentCenter = map.getCenter();
setCenter изменяет положение камеры, сохраняя остальные
параметры. getCenter возвращает текущее положение камеры в
координатах [lng, lat].
Важно понимать: центр камеры всегда связан с экранной геометрией —
это точка, которая проецируется в пиксель центра canvas
(width/2, height/2), независимо от
распределения объектов на карте.
Центроид — это геометрический центр фигуры,
вычисляемый на основе координат её вершин. В контексте GeoJSON это
характеристика конкретной геометрии: Point,
Polygon, MultiPolygon.
Для полигона центроид — это точка, которая минимизирует среднеквадратичное расстояние до всех точек фигуры или, в упрощённом виде, является “балансной точкой” площади.
Пример GeoJSON объекта:
const polygon = {
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [[
[69.2, 53.2],
[69.4, 53.2],
[69.4, 53.3],
[69.2, 53.3],
[69.2, 53.2]
]]
}
};
Несмотря на схожесть терминов, это принципиально разные концепции.
| Параметр | center (камера) | centroid (геометрия) |
|---|---|---|
| Природа | визуальная | математическая |
| Зависит от | положения карты | формы объекта |
| Меняется при pan/zoom | да | нет |
| Привязан к экрану | да | нет |
| Может быть вне объекта | да | да |
Если требуется поставить маркер “в центре объекта”, использование
map.getCenter() некорректно. Камера может быть смещена
пользователем.
Корректный подход — вычисление центроида:
import centroid from '@turf/centroid';
const centerPoint = centroid(polygon);
Далее:
new mapboxgl.Marker()
.setLngLat(centerPoint.geometry.coordinates)
.addTo(map);
Если требуется наоборот — переместить камеру так, чтобы объект оказался по центру экрана:
map.flyTo({
center: centerPoint.geometry.coordinates,
zoom: 12
});
Здесь происходит обратное преобразование: геометрический центроид становится центром камеры.
Для составных объектов простое усреднение координат даёт искажения. Корректный центроид должен учитывать площади частей.
Пример проблемы:
Правильный центроид:
Альтернативный способ получить “центр объекта” — использовать bounding box:
[minLng, minLat, maxLng, maxLat]
Центр вычисляется как:
const center = [
(minLng + maxLng) / 2,
(minLat + maxLat) / 2
];
В экосистеме Mapbox GL JS часто используется метод:
map.fitBounds(bounds);
Он автоматически вычисляет центр bounding box и подстраивает камеру.
Mapbox GL JS использует Web Mercator projection, в которой:
Один и тот же полигон:
Это приводит к тому, что:
Иногда требуется найти центр не в географических координатах, а в пикселях:
const centerPixel = map.project([lng, lat]);
И обратное преобразование:
const lngLat = map.unproject([x, y]);
Это важно при работе с UI-слоями, tooltip, overlay и кастомными контролами.
Если есть набор точек (например, результаты
queryRenderedFeatures):
const features = map.queryRenderedFeatures({ layers: ['points'] });
Можно вычислить средний центр:
let lngSum = 0;
let latSum = 0;
features.forEach(f => {
lngSum += f.geometry.coordinates[0];
latSum += f.geometry.coordinates[1];
});
const center = [
lngSum / features.length,
latSum / features.length
];
Однако такой подход игнорирует плотность и площадь влияния объектов.
В слоях типа symbol, circle,
heatmap центроид часто используется как:
map.addLayer({
id: 'labels',
type: 'symbol',
source: 'areas',
layout: {
'text-field': ['get', 'name'],
'text-anchor': 'center'
}
});
Здесь Mapbox автоматически использует центроид полигона для позиционирования текста.
При взаимодействии с картой центр камеры постоянно изменяется:
При этом геометрический центроид остаётся неизменным.
Это приводит к важному разделению:
map.fitBounds([
[69.1, 53.1],
[69.5, 53.5]
]);
Внутри этого метода:
Таким образом, fitBounds фактически работает через центр
bbox, а не через centroid геометрий.
В геоаналитике centroid используется для:
В Mapbox GL JS это часто комбинируется с GeoJSON sources:
map.addSource('regions', {
type: 'geojson',
data: geojsonData
});
Далее слой может использовать вычисленные центроиды как отдельный dataset.
center — параметр камеры, определяющий отображение
сценыЭти понятия формируют разные уровни одной системы: