Размеры и якорные точки иконок

В Leaflet отображение маркеров строится вокруг объекта иконки, который определяет не только изображение, но и его геометрию на карте. Ключевую роль в позиционировании играют размеры изображения и якорные точки, задающие привязку пиксельной графики к географической координате.


Размер иконки (IconSize)

Размер иконки определяет фактическую ширину и высоту изображения маркера в пикселях. В Leaflet он задаётся через параметр iconSize.

Основная цель — сообщить системе координат, как интерпретировать пиксельное изображение в пространстве карты.

L.icon({
  iconUrl: 'marker.png',
  iconSize: [38, 95]
});

Массив содержит два значения:

  • ширина изображения
  • высота изображения

При отсутствии явного размера Leaflet не способен корректно рассчитать позиционирование, особенно при сложных кастомных иконках и SVG-изображениях.


Якорная точка иконки (IconAnchor)

Якорная точка определяет, какой пиксель изображения будет привязан к координате маркера на карте.

(0,0)

По умолчанию координата маркера соответствует верхнему левому углу изображения, что редко используется на практике. Чаще всего требуется привязка к нижней центральной части иконки, чтобы «остриё» маркера указывало на точку на карте.

L.icon({
  iconUrl: 'marker.png',
  iconSize: [38, 95],
  iconAnchor: [19, 94]
});

Значения iconAnchor:

  • x — горизонтальное смещение от левого края
  • y — вертикальное смещение от верхнего края

Типовой шаблон:

  • центр по горизонтали: iconSize[0] / 2
  • низ по вертикали: iconSize[1]

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

PopupAnchor задаёт смещение всплывающего окна относительно точки привязки иконки.

Без корректной настройки всплывающее окно может перекрывать маркер или отображаться на значительном удалении.

L.icon({
  iconUrl: 'marker.png',
  iconSize: [38, 95],
  iconAnchor: [19, 94],
  popupAnchor: [0, -90]
});

Семантика смещения:

  • отрицательное значение по Y поднимает popup вверх
  • положительное значение по Y опускает popup вниз
  • X используется для горизонтального смещения

Обычно popup размещается над верхней частью маркера, поэтому используется отрицательное смещение по вертикали.


Тень и её размеры (shadowSize и shadowAnchor)

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

L.icon({
  iconUrl: 'marker.png',
  shadowUrl: 'shadow.png',
  iconSize: [38, 95],
  shadowSize: [50, 64],
  iconAnchor: [19, 94],
  shadowAnchor: [4, 62]
});

Особенности:

  • shadowSize определяет отображаемый размер тени
  • shadowAnchor задаёт точку привязки тени относительно координаты маркера

Тень визуально должна совпадать с положением иконки, иначе возникает эффект «отрыва» маркера от поверхности карты.


Центровка и типовые схемы привязки

Наиболее распространённая модель — нижнецентрированная иконка:

  • координата привязана к нижнему центру изображения
  • маркер визуально «стоит» на карте

Формула расчёта:

iconAnchor_x = , iconAnchor_y = iconSize_h

Такая схема используется для стандартных маркеров в большинстве картографических интерфейсов.


Дефолтная иконка Leaflet

Стандартный маркер Leaflet использует фиксированные параметры:

  • размер: 25×41 пиксель
  • якорь: [12, 41]
  • popupAnchor: [1, -34]

Эти значения оптимизированы под визуальный баланс стандартного SVG/PNG маркера.


Проблемы несоответствия размеров

Некорректная настройка размеров и якорей приводит к ряду визуальных ошибок:

  • маркер смещается относительно координаты
  • popup перекрывает иконку
  • тень «уезжает» в сторону
  • кластеризация даёт смещение при масштабировании

Особенно часто ошибки возникают при использовании:

  • изображений с прозрачными полями
  • SVG с нестандартным viewBox
  • ретина-иконок без отдельного масштабирования

Ретина-иконки и масштабирование

Для экранов с высокой плотностью пикселей используется параметр iconRetinaUrl. Он позволяет подменять изображение на более детализированное.

L.icon({
  iconUrl: 'marker.png',
  iconRetinaUrl: 'marker@2x.png',
  iconSize: [38, 95],
  iconAnchor: [19, 94]
});

Важно, что размеры iconSize остаются логическими (CSS-пиксели), а не физическими пикселями устройства.


CSS-класс и гибкое управление

Дополнительно иконки могут быть реализованы через divIcon, где размеры и якоря определяются через CSS.

L.divIcon({
  className: 'custom-marker',
  iconSize: [40, 40],
  iconAnchor: [20, 40]
});

CSS:

.custom-marker {
  width: 40px;
  height: 40px;
  background: red;
  border-radius: 50%;
}

В этом случае визуальная геометрия полностью контролируется стилями, а Leaflet управляет только позиционированием контейнера.


Спрайтовые иконки

При использовании sprite-sheet изображений размеры и якоря требуют особой точности. Одна иконка выделяется через смещение в CSS:

L.icon({
  iconUrl: 'sprites.png',
  iconSize: [32, 32],
  iconAnchor: [16, 32],
  className: 'sprite-marker'
});
.sprite-marker {
  background-position: -64px -32px;
}

Ошибки в расчёте iconSize приводят к смещению всех элементов спрайта.


Практика выравнивания элементов интерфейса

Согласованность достигается при соблюдении трёх базовых параметров:

  • размер изображения соответствует реальному визуальному блоку
  • якорь совпадает с точкой логической привязки
  • popupAnchor компенсирует высоту иконки

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


Геометрическая модель маркера

Маркер в Leaflet можно представить как двумерную систему координат изображения:

  • начало координат (0,0) — верхний левый угол
  • ось X направлена вправо
  • ось Y направлена вниз

Якорь задаёт точку:

A(x,y)

где эта точка сопоставляется с географической координатой на карте.


Влияние масштаба карты

При изменении масштаба карты иконка не изменяет размеры, если не используется CSS-трансформация или кластеризация. Однако смещение popup и anchor остаётся фиксированным в пикселях экрана, что делает корректную настройку критически важной для стабильного поведения интерфейса.


Согласование нескольких типов маркеров

В приложениях с разными типами иконок (например, категории объектов) используется унификация:

  • единый базовый размер
  • единая точка привязки
  • согласованные popupAnchor значения

Это позволяет сохранять визуальную целостность при смешанном отображении различных слоёв данных.