MapLibre GL JS реализует камеру карты как абстракцию над трансформацией мира в экранное пространство. Одним из ключевых механизмов позиционирования является вычисление параметров камеры по географическим границам — прямоугольнику, заданному координатами юго-западного и северо-восточного углов. Внутренняя логика, условно обозначаемая как CameraForBounds, отвечает за преобразование географического bounding box в набор параметров камеры: центр, zoom, bearing и pitch.
Границы карты задаются в виде:
[lng, lat][lng, lat]Такой прямоугольник в географической системе координат описывает область, которую необходимо полностью поместить в видимую часть экрана.
В основе вычислений лежит проекция Web Mercator projection, которая переводит сферические координаты в плоскость. Это позволяет корректно работать с расстояниями и масштабированием на разных широтах.
CameraForBounds формирует камеру на основе следующих шагов:
Результатом становится объект камеры:
Каждая точка bounds проходит трансформацию:
worldPoint = project(lng, lat)
Где projection основана на Web Mercator:
Это позволяет учитывать искажения карты при приближении к полюсам.
Центр bounds вычисляется как среднее в мировом пространстве:
centerWorld = (minWorld + maxWorld) / 2
После чего выполняется обратное преобразование:
centerLngLat = unproject(centerWorld)
Центр камеры становится опорной точкой всей трансформации.
Ключевая задача CameraForBounds — подобрать такой zoom, при котором прямоугольник полностью помещается в viewport.
Используется принцип:
Формально:
Padding позволяет смещать визуальное центрирование внутрь viewport, оставляя поля:
Фактически viewport уменьшается до:
effectiveWidth = width - left - right
effectiveHeight = height - top - bottom
CameraForBounds выполняет расчёты уже на этом уменьшенном пространстве, что влияет на итоговый zoom и center.
При вычислении камеры из bounds значения:
обычно сохраняются из текущего состояния камеры, если явно не переопределены. Это позволяет сохранить визуальный стиль сцены при переходе между регионами.
После вычисления базового zoom применяется clamp:
zoom = Math.max(minZoom, Math.min(maxZoom, zoom))
Это предотвращает:
CameraForBounds является основой метода:
map.fitBounds([
[minLng, minLat],
[maxLng, maxLat]
], {
padding: 40,
duration: 1000
});
Алгоритм:
Web Mercator вносит нелинейность по оси Y. Это означает:
CameraForBounds компенсирует это через работу в projected space, а не в lat/lng напрямую.
При ненулевом bearing bounding box перестает быть осесимметричным в экранных координатах.
Алгоритм:
При частых обновлениях bounds (анимации, потоковые данные) применяются:
Это предотвращает дрожание карты.
CameraForBounds является частью цепочки:
Внутренний transform state хранит:
При bounds, пересекающих анти-меридиан:
CameraForBounds часто применяется в сценариях:
При transition:
CameraForBounds формирует стартовое и конечное состояние, между которыми строится анимация.
Любое изменение:
немедленно изменяет результат CameraForBounds, поскольку перерасчет выполняется в пиксельной системе координат.
Типовой pipeline:
const bounds = [
[minLng, minLat],
[maxLng, maxLat]
];
map.fitBounds(bounds, {
padding: 80,
maxZoom: 14
});
Внутри это эквивалентно:
CameraForBounds можно рассматривать как функцию:
f(bounds, viewport, padding, rotation, constraints)
→ camera(center, zoom, bearing, pitch)
где ключевым фактором является преобразование геометрии мира в ограниченное экранное пространство с учетом всех ограничений рендеринга и проекции.