В Leaflet работа с геометрией карты опирается на несколько уровней координатных преобразований. Помимо привычных географических координат (широта и долгота), библиотека активно использует промежуточные экранные системы координат, позволяющие корректно отображать объекты на разных масштабах и проекциях.
Одними из ключевых методов низкоуровневого взаимодействия с системой
координат слоя являются latLngToLayerPoint и
layerPointToLatLng. Эти функции обеспечивают двустороннее
преобразование между географическими координатами и координатами слоя
(layer points), которые представляют собой пиксельные координаты внутри
текущего слоя карты с учётом зума и проекции.
Внутри Leaflet существует несколько уровней представления координат:
Разделение важно:
Методы latLngToLayerPoint и
layerPointToLatLng работают именно с
LayerPoint, который является фундаментом для отрисовки
объектов внутри системы карты.
Метод преобразует географические координаты в координаты слоя.
map.latLngToLayerPoint(latlng)
Преобразует:
LatLng (широта/долгота) → LayerPoint (x, y в пикселях слоя)
Каждая географическая точка проецируется в двумерное пространство, после чего масштабируется в соответствии с уровнем zoom.
Упрощённо:
worldCoordinate = projection(latlng)
layerPoint = worldCoordinate * scale(zoom)
const latlng = L.latLng(55.751244, 37.618423);
const point = map.latLngToLayerPoint(latlng);
console.log(point.x, point.y);
При работе с Canvas-слоями необходимо переводить географические координаты в пиксельные:
function drawPoint(ctx, latlng) {
const point = map.latLngToLayerPoint(latlng);
ctx.beginPath();
ctx.arc(point.x, point.y, 5, 0, Math.PI * 2);
ctx.fill();
}
При изменении позиции объекта в реальном времени:
function moveObject(latlng) {
const point = map.latLngToLayerPoint(latlng);
element.style.transform = `translate(${point.x}px, ${point.y}px)`;
}
Метод используется при создании кастомных overlay-слоёв, где требуется полный контроль над рендерингом.
Обратное преобразование: из пиксельных координат слоя в географические координаты.
map.layerPointToLatLng(point)
Преобразует:
LayerPoint (x, y в пикселях слоя) → LatLng (широта/долгота)
latLngToLayerPointconst point = L.point(200, 150);
const latlng = map.layerPointToLatLng(point);
console.log(latlng.lat, latlng.lng);
При работе с кастомным canvas-слоем часто требуется преобразовать координаты клика:
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const layerPoint = L.point(
e.clientX - rect.left,
e.clientY - rect.top
);
const latlng = map.layerPointToLatLng(layerPoint);
console.log(latlng);
});
Если имеется изображение или графический слой, привязанный к карте:
function getGeoFromPixel(x, y) {
const latlng = map.layerPointToLatLng(L.point(x, y));
return latlng;
}
При создании редакторов (например, рисование полигонов) важно переводить координаты мыши:
const startLatLng = map.layerPointToLatLng(startPoint);
const endLatLng = map.layerPointToLatLng(endPoint);
Ключевая ошибка при работе с Leaflet — путаница между системами координат.
map.on('click', (e) => {
console.log(e.containerPoint); // пиксели в окне
console.log(e.layerPoint); // пиксели в системе карты
console.log(e.latlng); // географические координаты
});
Обе функции опираются на внутреннюю проекцию карты.
В большинстве случаев используется:
Проекция преобразует:
(lat, lng) → (x, y) в мировом пространстве
Далее применяется масштабирование:
x, y → layerPoint (с учётом zoom)
При увеличении масштаба:
map.setZoom(10);
const p1 = map.latLngToLayerPoint(latlng);
map.setZoom(15);
const p2 = map.latLngToLayerPoint(latlng);
p1 и p2 будут существенно различаться, хотя
LatLng одинаков.
При разработке собственных слоёв важно выполнять преобразование в обе стороны:
const point = map.latLngToLayerPoint(feature.latlng);
draw(point);
const latlng = map.layerPointToLatLng(point);
updateModel(latlng);
Приводит к смещению объектов при zoom.
LayerPoint необходимо пересчитывать при изменении состояния карты:
map.on('move zoom', redraw);
Нельзя сохранять layerPoint между изменениями zoom:
// неверно
const cached = map.latLngToLayerPoint(latlng);
map.setZoom(12);
// cached устарел
Часто используются вместе:
map.latLngToContainerPointmap.containerPointToLatLngmap.latLngToLayerPointmap.layerPointToLatLngЭто образует полную систему двусторонних преобразований:
LatLng ↔ ContainerPoint
LatLng ↔ LayerPoint
LayerPoint ↔ LatLng
LayerPoint удобен для вычислений:
const p1 = map.latLngToLayerPoint(a);
const p2 = map.latLngToLayerPoint(b);
const dx = p1.x - p2.x;
const dy = p1.y - p2.y;
const distance = Math.sqrt(dx * dx + dy * dy);
const triangle = [
map.latLngToLayerPoint(a),
map.latLngToLayerPoint(b),
map.latLngToLayerPoint(c)
];
Использование latLngToLayerPoint и обратного метода
напрямую влияет на производительность при большом количестве
объектов.
Рекомендации:
Внутренний pipeline Leaflet строится вокруг layerPoint как промежуточного представления:
LatLng → World Coordinate → LayerPoint → Rendering (Canvas/SVG/DOM)
И обратный путь:
Event Pixel → LayerPoint → LatLng → Application Logic